hdu5439(打表找规律)

来源:互联网 发布:家园2 网络不可用 编辑:程序博客网 时间:2024/05/17 09:41

题目链接:hdu5439


题目大意:首先写下第一秒再纸上写上1,2,第二秒在纸上写上1个2,第三秒在纸上写上2个3(现在纸上是1,2,2,3,3)……假设纸上的数字组成一个数组b[i],第i秒在纸上写下的数字为b[i]个i,现在求出i*b[i]前n项的和。


题目分析:既然第i秒在纸上写下了b[i]个数字,那么不妨求出在第i秒纸上一共有多少数字,这样当给出n的时候,可以利用二分轻松的得出此时在纸上写的是什么数字。第n项时可能并不是i刚好写完,所以需要特殊处理一下,但是对于之前的数字则可以根据规律用公式算出。打表之后很容易得到下面这个式子。ans=1 + (2+3)*2 + (4+5)*3 + (6+7+8)*4 + ... + (...+n)*t,式子括号里面的数字时b数组中相等的部分的下标。交上去之后发现还是超时,这是因为对于每个样例都要计算一下这个式子,而这个t很大,最大好像可以达到48万多,所以需要预处理一下就可以了。


代码:

#include <vector>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;typedef long long LL;const int mod=1e9+7;const int maxn=500000+100;int T,n,cnta=4;LL ans[maxn];int a[maxn],sum[maxn];//等差数组求和(因为括号中的数字为等差数列)LL cal(LL a,LL b){    LL ans=0;    ans=(((a+b)*(b-a+1))/2)%mod;    return ans;}void init(){    //打出b数组    int now=3;    a[1]=1;a[2]=2;a[3]=2;    sum[1]=1;sum[2]=3;sum[3]=5;    for(int i=3;cnta+1<maxn;i++){        int val=a[i];        while(val--)        {            sum[cnta]=sum[cnta-1]+now;            if(cnta+1>=maxn)   break;            a[cnta++]=now;        }        now++;    }    //预处理    for(int i=2;i<maxn;i++){        ans[i]=(ans[i-1]+cal((LL)sum[i-1]+1,(LL)sum[i])*i%mod)%mod;    }}//搜索出第n项的数字int Search(){    int l=1,r=cnta,mid;    while(l<r)    {        mid=(l+r)/2;        if(sum[mid]==n){            return mid;        } else if(sum[mid]<n){            if(sum[mid+1]>=n)   return mid+1;            l=mid+1;        } else {            if(sum[mid-1]<n)    return mid;            if(sum[mid-1]==n)   return mid-1;            r=mid-1;        }    }    return -1;}int solve(){    if(n==0)    return 0;    LL val=1;    int maxi=Search();    //如果第n秒数字还没有写完    if(sum[maxi]>n){        val=(val+cal(sum[maxi-1]+1,n)*maxi)%mod;        maxi--;    }    //第n秒所写数字之前的和    if(maxi>=2){        val=(val+ans[maxi])%mod;    }    return val;}int main(){//    freopen("in.txt","r",stdin);//    freopen("out.txt","w",stdout);    ios::sync_with_stdio(false);    init();    for(cin>>T;T--;){        cin>>n;        cout<<solve()<<endl;    }    return 0;}


原创粉丝点击