51nod-1138 连续整数的和(预处理)

来源:互联网 发布:东华软件新闻 编辑:程序博客网 时间:2024/06/05 21:03

1138  连续整数的和

给出一个正整数N,将N写为若干个连续数字和的形式(长度 >= 2)。例如N = 15,可以写为1 + 2 + 3 + 4 + 5,也可以写为4 + 5 + 6,或7 + 8。如果不能写为若干个连续整数的和,则输出No Solution。
Input
输入1个数N(3 <= N <= 10^9)。
Output
输出连续整数中的第1个数,如果有多个按照递增序排列,如果不能分解为若干个连续整数的和,则输出No Solution。
Input示例
15
Output示例
147

题解:

直接枚举超时,分析题中的数据,我们可以发现有这样的关系:2N = n(n-1+2a) (其中a为序列的首项,n为序列的项数),稍微化解就可以N = (n-1)n/2 + na;这样我们可以对1e9之内的所有可以等于n(n-1)/2 (n为整数)的数预处理出来然后这样枚举n(n-1)/2就可以了,就优化为了O(sqrt(n))的复杂度。具体实现见代码。

代码:

#include<iostream>#include<cstring>#include<math.h>#include<stdlib.h>#include<cstring>#include<cstdio>#include<utility>#include<algorithm>#include<map>#include<stack>using namespace std;typedef long long ll;const int Max = 1e5+5;const int mod = 1e9+7;const int Hash = 10000;const int INF = 1<<30;const ll llINF = 1e18;int n, cnt;ll arr[Max];ll f(int x){    return (x-1)*x/2;}void init( ){    cnt = 2;    ll t = f(cnt);    while(t <= 1e9)    {        arr[cnt] = t;        cnt++;        t = f(cnt);    }}int main( ){    //freopen("input.txt", "r", stdin);    init( );//N = (n-1)*n/2 + na;所以可以提前将n(n-1)/2枚举出来是O(sqrt(N))复杂度    while(cin>>n)    {        int i= 2;        stack<int> st;        while(arr[i] < n)        {            int a = (n-arr[i])/i;            if(a*i == n-arr[i])                st.push(a);            i++;        }        if(st.empty( ))        {            cout<<"No Solution"<<endl;            continue;        }        while(!st.empty( ))        {            printf("%d\n", st.top());            st.pop( );        }    }    return 0;}


原创粉丝点击