题目大意:
给定n、m,求出(1--n)所有数与(1--m)所有数的gcd之和。
看完题解后可以发现一个有用的结论:
对于一个数,他的所有因子的欧拉值之和等于这个数本身。
例如8这个数字,他的因子分别有1,2,4,8,对应欧拉值为1,1,2,4。
那么我们可以对题目的询问做一下改变。
对于gcd(i,j)的值,我们可以求出他所有因子的欧拉值,加起来即为gcd(i,j)的值。
换一个思路,我们枚举每一个因子,看他作为哪一对(i,j)的一个因子出现,每有一对贡献就+1。
而枚举到x时,对数很容易发现是(m/x)*(n/x)。
那么这个因子的总贡献即为phi[x]*(m/x)*(n/x)。
附上代码:
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const int inf=1e7+10; 5 const int mod=998244353; 6 int n,m; 7 bool p[inf]; 8 vector<int>pls; 9 ll phi[inf]; 10 void get_phi(int x){ 11 phi[1]=1; 12 for(int i=2;i<=x;i++){ 13 if(!p[i]){ 14 pls.push_back(i); 15 phi[i]=i-1; 16 } 17 int siz=pls.size(); 18 for(int j=0;j<siz&&pls[j]*i<=n;j++){ 19 p[i*pls[j]]=1; 20 if(i%pls[j]==0){ 21 phi[i*pls[j]]=phi[i]*pls[j]%mod; 22 break; 23 } 24 else phi[i*pls[j]]=phi[i]*(pls[j]-1)%mod; 25 } 26 } 27 } 28 int main() 29 { 30 freopen("hoip.in","r",stdin); 31 freopen("hoip.out","w",stdout); 32 scanf("%d%d",&n,&m); 33 if(n>m)swap(n,m); 34 get_phi(n); 35 ll ans=0; 36 for(int i=1;i<=n;i++){ 37 ans+=phi[i]*(m/i)%mod*(n/i)%mod; 38 ans%=mod; 39 } 40 printf("%lld\n",ans); 41 return 0; 42 }
代码君
时间: 2024-11-05 13:28:39