BZOJ1257
模转除, 整除分块就可以了
#include<bits/stdc++.h>
#define LL long long
using namespace std;
int n,k; LL ans;
int main(){
scanf("%d%d",&n,&k);
ans = (LL)k * (LL)n;
LL ret = 0;
for(int l=1,r;l<=n;l=r+1){
if(k/l==0) break;
r = k/(k/l); if(r>n) r = n;
ret += (LL)(k/l) * (LL)(l+r) * (LL)(r-l+1) / 2 ;
} printf("%lld", ans - ret);
return 0;
}
BZOJ 2226
枚举一下gcd
然后线性筛+调和级数预处理一下就可以了
#include<bits/stdc++.h>
#define N 1000050
#define LL long long
using namespace std;
int prim[N],isp[N],tot,phi[N];
LL val[N],ans[N];
void prework(){
phi[1] = 1;
for(int i=2;i<=N-50;i++){
if(!isp[i]) prim[++tot] = i, phi[i] = i-1;
for(int j=1;j<=tot;j++){
if(i*prim[j] > N-50) break;
isp[i * prim[j]] = 1;
if(i%prim[j]==0){ phi[i*prim[j]] = phi[i] * prim[j]; break;}
else phi[i*prim[j]] = phi[i] * (prim[j] - 1);
}
}
val[1] = 1;
for(int i=2;i<=N-50;i++) val[i] = (LL)phi[i] * (LL)i / 2ll;
for(int i=1;i<=N-50;i++)
for(int j=i;j<=N-50;j+=i) ans[j] += val[i];
}
int main(){
prework(); int T; scanf("%d",&T);
while(T--){ int n; scanf("%d",&n); printf("%lld\n",(LL)n*ans[n]);}
return 0;
}
BZOJ2705
#include<bits/stdc++.h>
#define LL long long
using namespace std;
LL ans,n;
int phi(int x){
int ans = x;
for(int i=2;i*i<=x;i++){
if(x % i == 0){
ans = ans / i * (i-1);
while(x % i == 0) x /= i;
}
}
if(x > 1) ans = ans / x * (x-1);
return ans;
}
int main(){
scanf("%lld",&n);
for(int i=1; i*i <= n; i++){
if(n%i == 0){
ans += (LL)i * (LL)phi(n/i);
if(i*i != n) ans += (LL)(n/i) * (LL)phi(i);
}
} printf("%lld",ans); return 0;
}