渊哥给我这题,我还以为是反演,然后还真推出来了
$$ans=sum_{d=1}(lfloorfrac{n}{i} floor)^2sum_{i|d}mu(frac{d}{i})i$$
然后51nod 跑了3sec T了
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cstdlib> #define ll long long #define mem(a,b) memset(a,b,sizeof(a)) using namespace std; inline int read() { char q=getchar();int ans=0; while(q<'0'||q>'9')q=getchar(); while(q>='0'&&q<='9'){ans=ans*10+q-'0';q=getchar();} return ans; } const int N=5000006; int prime[N],cnt; bool he[N]; ll ji[N]; void chu() { ji[1]=1; for(int i=2;i<N;++i) { if(!he[i]) { prime[++cnt]=i; ji[i]=i-1; } for(int j=1;j<=cnt&&prime[j]*i<N;++j) { he[i*prime[j]]=1; if(i%prime[j]==0) { ji[i*prime[j]]=ji[i]*prime[j]; break; } ji[i*prime[j]]=ji[i]*ji[prime[j]]; } } for(int i=1;i<N;++i) ji[i]+=ji[i-1]; } int T,n; int main(){ //freopen("in.in","r",stdin); chu(); T=read(); ll ans; int nx; while(T--) { n=read(); ans=0; for(int i=1;i<=n;i=nx+1) { nx=n/(n/i); ans+=(ll)(n/i)*(n/i-1)*(ji[nx]-ji[i-1]); } printf("%lld ",ans/2); } }
正解是
要求 gcd(n,i)==K 的数量,可以转化成求 gcd(n/K,i/K)==1 的个数
$$ans=sum_{i=2}^nsum_{j=1}^{i-1}gcd(i,j)$$
$$ans=sum_{i=2}^nsum_{j|i}^{i-1}phi(frac{i}{j})j$$
$$ans=sum_{i=2}^nsum_{j=1}^{i*j<=n}phi(i)j$$
$O(nlog(n))$
正解也会T,51nod真玄学
#pragma GCC optimize("O3") #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cstdlib> #define ll long long #define mem(a,b) memset(a,b,sizeof(a)) using namespace std; inline int read() { char q=getchar();int ans=0; while(q<'0'||q>'9')q=getchar(); while(q>='0'&&q<='9'){ans=ans*10+q-'0';q=getchar();} return ans; } const int N=5000006; const int TT=50006; int prime[348600],cnt; bool he[N]; int ou[N]; ll an[N]; void chu() { ou[1]=1; for(int i=2;i<N;++i) { if(!he[i]) { prime[++cnt]=i; ou[i]=i-1; } for(int j=1;j<=cnt&&prime[j]*i<N;++j) { he[i*prime[j]]=1; if(i%prime[j]==0) { ou[i*prime[j]]=ou[i]*prime[j]; break; } ou[i*prime[j]]=ou[i]*ou[prime[j]]; } } ll t1; for(int i=2;i<N;++i) for(int j=1;j*i<N;++j) an[i*j]+=ou[i]*j; for(int i=2;i<N;++i) an[i]+=an[i-1]; } int T,n; int main(){ //freopen("in.in","r",stdin); //freopen("51nod_Problem_1188_Test_21_In.txt","r",stdin); //freopen("out.out","w",stdout); chu(); scanf("%d",&T); while(T--) { scanf("%d",&n); printf("%lld ",an[n]); } }