GCD SUM 強大的數論,容斥定理
阿新 • • 發佈:2019-01-31
GCD SUM
Time Limit: 8000/4000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others)Problem Description
給出N,M執行如下程式:
long long ans = 0,ansx = 0,ansy = 0;
for(int i = 1; i <= N; i ++)
for(int j = 1; j <= M; j ++)
if(gcd(i,j) == 1) ans ++,ansx += i,ansy += j;
cout << ans << " " << ansx << " " << ansy << endl;
Input
多組資料,每行兩個數N,M(1 <= N,M <= 100000)。
Output
如題所描述,每行輸出3個數,ans,ansx,ansy,空格隔開Sample Input
5 5
1 3
Sample Output
19 55 55
3 3 6
#include <iostream> #include <stdio.h> #include <string.h> using namespace std; #define MAX 100010 #define ll long long ll mu[MAX]= {0},mb[MAX]= {0}; void init() { int i,j; for(i=2; i<MAX; i++) { if(!mu[i]) { mu[i]=i; if(i>1000)continue; j=i*i; while(j<MAX) { mu[j]=i; j+=i; } } } mu[1]=1; for(i=2; i<MAX; i++) { if((i/mu[i])%mu[i]==0)mu[i]=0; else mu[i]=-mu[i/mu[i]]; } for(i=1; i<MAX; i++) mb[i]=mu[i]*i,mu[i]+=mu[i-1],mb[i]+=mb[i-1]; } void solve(int n,int m) { ll ans,ansx,ansy,x,y; ans=ansx=ansy=0; int i,j,k; for(i=(n>m?m:n);i>0;) { x=n/i,y=m/i; k=max(n/(x+1),m/(y+1)); ans+=x*y*(mu[i]-mu[k]); ansx+=(mb[i]-mb[k])*y*(1+x)*x/2; ansy+=(mb[i]-mb[k])*x*(1+y)*y/2; i=k; } printf("%lld %lld %lld\n",ans,ansx,ansy); } int main() { init(); int n,m; while(scanf("%d%d",&n,&m)!=EOF) { solve(n,m); } }