https://ac.nowcoder.com/acm/contest/5673/E
设我们要算出f[1-n],那么枚举a,a+1,a+2的个数,要满足x*a+(a+1)*y+(a+2)*z=1-n的数量
提取一下,(x+y+z)*a+y+2*z=1-n的数量,其中a,x,y,z>=1
那我们先求出a<=sqrt(n)的所有情况,然后去枚举i,得到a<=r下,f[1-n]的增加的值,这里是nsqrt(n)的复杂度
然后我们就只要去算sqrt(n)<a<=n时,f[1-n]能增加的方案数了
我们令s=x+y+z,t=y+2*z,由s*a+t<=n,s<=sqrt(n),
令c[s][t]为x+y+z=s,y+2*z=t 时的(x,y,z)构造的方案数,这个可以通过简单的枚举x,y,z得到,是nsqrt(n)的复杂度
然后枚举a=sqrt(n)->n,对于每个a枚举s*a<=n再枚举t<=2*s,这一段通过积分可以知道也是nsqrt(n)的复杂度
所以总复杂度还是nsqrt(n),就可以算出f[1-n]的所有值
#include<bits/stdc++.h>
using namespace std;
int f[200005];
long long c[2005][2005];
long long S[200005];
int main(){
int n=100000,r=(int)sqrt(n+0.5),a;
for(a=1;a<=r;a++){
for(int i=3*a+3;i<=n;i+=a)f[i]=1;
for(int m=4*a+4;m<=n;m++)f[m]+=f[m-a-1];
for(int m=4*a+5;m<=n;m++)f[m]+=f[m-a-2];
for(int i=3*a+3;i<=n;i++)S[i]+=f[i],f[i]=0;
}
for(int x=1;x<=r;x++){
for(int y=1;x+y<=r;y++){
for(int z=1;x+y+z<=r;z++){
c[x+y+z][y+2*z]++;
}
}
}
for(;a<=n;a++){
for(int s=3;s*a<=n;s++){
for(int t=3;t<=2*s;t++){
if(s*a+t<=n)S[s*a+t]+=c[s][t];
else break;
}
}
}
for(int i=1;i<=n;i++)S[i]+=S[i-1];
int t;
scanf("%d",&t);
for(int ti=1;ti<=t;ti++){
int l,r;
scanf("%d%d",&l,&r);
printf("Case #%d: %lld\n",ti,S[r]-S[l-1]);
}
return 0;
}