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

 

转载于:https://www.cnblogs.com/hyghb/p/7853801.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值