题解:
首先我们设gcd(i,j)=k
所以我们就要求对于所有k的方案总数
可以线性帅选欧拉函数
然后算法一:枚举k,O(NT)
算法二:考虑到我们只要n/k的整数部分
容易证明是sqrt(n)级别的
所以就可以在O(Tsqrt(n))的时间内解决
但是要考虑卡常数
代码:
#include<bits/stdc++.h> typedef long long ll; const int N=1000010; ll ans,res[N],g[N],s[N]; int p[N],f[N],len=0,n,a[N],b[N],tmp; int main() { freopen("1.in","r",stdin); freopen("1.out","w",stdout); for (int i=2;i<N;i++) { if (!f[i])f[i]=i,p[++len]=i; for (int j=1;j<=len&&p[j]<=f[i]&&p[j]<=N/i;j++)f[i*p[j]]=p[j]; } for (int i=2;i<N;i++) { if (f[i]==i) g[i]=i-1; else { int x=i/f[i]; if (f[i]==f[x]) g[i]=g[x]*f[i]; else g[i]=g[x]*(f[i]-1); } } for (int i=1;i<N;i++) { s[i]=s[i-1]+i; g[i]+=g[i-1]; res[i]=-1; } while (scanf("%d",&n),n) { ans=0; int j; for (j=1;j*j<=n;j++) { a[j]=n/j; ans+=g[a[j]]*j; } for (int k=n/j;j<=n;k--) { ans+=g[k]*(s[a[k]]-s[j-1]); j=a[k]+1; } res[n]=ans; printf("%lld ",ans); } }