题意![这里写图片描述](https://img-blog.csdn.net/20170704193652314?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvQ0hITlo=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
题解
我们设
g(i)=i2−3i+2
,题目告诉我们的就是
g=f∗1
。然后就可以根据杜教筛的思路搞了:
∑i=1ng(i)=∑i=1n∑d|if(d)=∑i=1n∑d⌊ni⌋f(d)=∑i=1nS(⌊ni⌋)
S(n)=∑i=1ng(i)−∑i=2nS(⌊ni⌋)
如何不预处理前面一部分的话 O(n34) 可能会T掉,所以先要求一段,怎么求呢?
反演一下, g=f∗1 , f(n)=(g∗μ)(n)=∑d|ng(d)∗μ(nd) ,然后 nlnn 暴力算就好了。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<tr1/unordered_map>
using namespace std;
using namespace std::tr1;
typedef long long LL;
const int N=1000000, maxn=N+5;
const LL MOD=1000000007, inv=(MOD+1)/3;
int Q,p[maxn],mu[maxn];
bool vis[maxn];
int sum[maxn];
void Pre(){
memset(vis,1,sizeof(vis));
mu[1]=1;
for(int i=2;i<=N;i++){
if(vis[i]) p[++p[0]]=i, mu[i]=-1;
for(int j=1;j<=p[0]&&p[j]*i<=N;j++){
vis[p[j]*i]=false;
if(i%p[j]==0){ mu[p[j]*i]=0; break; }
mu[p[j]*i]=-mu[i];
}
}
for(int i=1;i<=N;i++)
for(int j=1;(LL)i*j<=N;j++) (sum[i*j]+=((LL)i-1)*(i-2)*mu[j]%MOD)%=MOD;
for(int i=1;i<=N;i++) (sum[i]+=sum[i-1])%=MOD;
}
unordered_map<int, int> lst;
int Sum(int n){
if(n<=N) return (sum[n]+MOD)%MOD;
if(lst.find(n)!=lst.end()) return lst[n];
int res=((LL)n)*(n-1)%MOD*(n-2)%MOD*inv%MOD;
for(LL i=2,nxt;i<=n;i=nxt+1){
nxt=n/(n/i); (res+=MOD-(nxt-i+1)*Sum(n/i)%MOD)%=MOD;
}
return lst[n]=(res+MOD)%MOD;
}
int main(){
freopen("hdu5608.in","r",stdin);
freopen("hdu5608.out","w",stdout);
Pre();
scanf("%d",&Q);
while (Q--){
int n; scanf("%d",&n);
printf("%d\n",Sum(n));
}
return 0;
}