码迷,mamicode.com
首页 > 其他好文 > 详细

cogs2745[济南集训 2017] 求gcd之和【解题报告】

时间:2017-11-17 23:31:22      阅读:275      评论:0      收藏:0      [点我收藏+]

标签:long   一个   size   mod   ati   out   ack   hid   scan   

题目链接

题目大意:

给定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 }
代码君

 

cogs2745[济南集训 2017] 求gcd之和【解题报告】

标签:long   一个   size   mod   ati   out   ack   hid   scan   

原文地址:http://www.cnblogs.com/Turkeyghb/p/7853801.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!