题意:
求 ∑NK=1Ngcd(N,K) . 有 106 个询问, N≤107 。
思路:
首先证明出
答案应该是
∑d⋅φ(d)
对所有的
d
为
这个具体的证明可以参考 SPOJ LCMSUM (数论),然后如果我们先线性预处理出了
1
-
注意到关于欧拉函数的下列性质:
所以我们可以利用性质1和2,做到
logN
内回答每一个询问:
N=k∗pe
, p为最大的质数,这个可以预处理的。
由性质1:
ans=∑d|Ndφ(d)=∑α=0e∑d|kdpαφ(dpα)=∑α=0e∑d|kdφ(d)pαφ(pα)=(∑α=0epαφ(pα))⎛⎝∑d|kdφ(d)⎞⎠,
第一部分可以由性质2得到,第二部分就直接计算咯(也可以实现预处理 ans[i] , 1≤i≤106 )!
代码:
#include <bits/stdc++.h>
#define dibs reserve
#define OVER9000 1234567890
#define ALL_THE(CAKE,LIE) for(auto LIE =CAKE.begin(); LIE != CAKE.end(); LIE++)
#define tisic 47
#define soclose 1e-8
#define chocolate win
// so much chocolate
#define patkan 9
#define ff first
#define ss second
#define abs(x) ((x < 0)?-(x):x)
#define uint unsigned int
#define dbl long double
#define pi 3.14159265358979323846
using namespace std;
// mylittledoge
int main()
{
cin.sync_with_stdio(0);
cin.tie(0);
int mx =10000000;
vector<int> minD(mx+tisic,0);
for(int i =2; i <= mx; i++) if(minD[i] == 0)
for(int j =1; j <= mx/i; j++) minD[i*j] =i;
int T;
scanf(" %d",&T);
while(T--) {
int N;
long long ans =1;
scanf(" %d",&N);
while(N > 1) {
int p =minD[N], ppw =1;
while(N%p == 0) {
ppw *=p;
N /=p;
}
ans *=1LL*ppw*ppw-(1LL*ppw*ppw-1)/(p+1);
}
printf("%lld\n",ans);
}
return 0;
}