NOIP 模拟赛 nan (暴力?)

来源:互联网 发布:wifi网络老是断断续续 编辑:程序博客网 时间:2024/05/16 02:37

这里写图片描述

思路

这道题。。。我找不到匹配的算法。。。
刚开始想打表,发现时间空间都要炸。然后准备推个公式,发现不好推。
回归打表大暴力。选择分块打表,按照数字的个数分块,发现剩下的都是等差数列。记住,加一下%一下,开long long不要爆了。
然后查找的时候二分一下,效率efficiency。
打表的话,好像只要60、70W就好了。

代码

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<cmath>#include<vector>using namespace std;const int mod=1000000007;const int N=1400000+10;int T,a[N];long long sum[N],pre[N];void init() {    a[1]=1;a[2]=a[3]=2;    long long last=3,cur=3;    while(true)     {        for (int i=last+1;i<=last+a[cur];i++) a[i]=cur;        last+=a[cur];        cur++;        if (last+a[cur]>N) break;    }    for (int i=1;i<=N;i++) sum[i]=sum[i-1]+a[i];    last=0;    for (int i=1;i<=N;i++)     {        long long L=last+1,R=last+a[i];        pre[i]=((long long)a[i]*((long long)L+R)>>1)%mod*i%mod;        (pre[i]+=pre[i-1])%=mod;        last=R;    }}int main() {    freopen("nan.in","r",stdin);    freopen("nan.out","w",stdout);    init();    scanf("%d",&T);    while(T--)     {        int n;        scanf("%d",&n);        int pos=upper_bound(sum+1,sum+N+1,n)-sum-1;        long long ans=pre[pos];        if(sum[pos]<n)         {            long long len,L,R;            len=n-sum[pos];            L=sum[pos]+1;            R=sum[pos]+len;            pos++;            ans+=((long long)len*((long long)L+R)>>1)%mod*pos%mod;            ans%=mod;        }        printf("%I64d\n",ans);    }    return 0;}
原创粉丝点击