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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了cogs2745[济南集训 2017] 求gcd之和解题报告相关的知识,希望对你有一定的参考价值。

题目链接

题目大意:

给定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之和解题报告的主要内容,如果未能解决你的问题,请参考以下文章

2741. [济南集训 2017] 掰巧克力

2017 济南集训DAY1.AF

济南集训随机分数

noip济南集训-10.1上午

noip济南集训-10.1上午

济南集训20191001解题报告