思路
这道题。。。我找不到匹配的算法。。。
刚开始想打表,发现时间空间都要炸。然后准备推个公式,发现不好推。
回归打表大暴力。选择分块打表,按照数字的个数分块,发现剩下的都是等差数列。记住,加一下%一下,开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;
}