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 }

代码君

时间: 2024-08-30 04:41:37

cogs2745[济南集训 2017] 求gcd之和【解题报告】的相关文章

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

★   输入文件:bpmp.in   输出文件:bpmp.out   简单对比 时间限制:1 s   内存限制:256 MB [题目描述] yyy收到了一块 n×m 的巧克力. 因为 hja的嘴太小所以yyy必需把巧克力掰成1×1 大小. yyy每次都只能把单独的一块巧克力沿某个分隔线掰成两瓣. 求yyy最小要掰多少次. 因 为 hja不会做太大的整数加法,所 以 yyy让 你 把 答 案 对 998244353取模. [输入格式] 输入一行两个正整数n,m [样例输入] 2 2 [样例输出]

2017 09 17 测验解题报告

预计分数 100+100+20 >=220 实际分数 100+50+20 =170 T1 :100 巧克力棒(chocolate)Time Limit:1000ms Memory Limit:64MB题目描述 LYK 找到了一根巧克力棒,但是这根巧克力棒太长了,LYK 无法一口吞进去.具体地,这根巧克力棒长为 n,它想将这根巧克力棒折成 n 段长为 1 的巧克力棒,然后慢慢享用. 它打算每次将一根长为 k 的巧克力棒折成两段长为 a 和 b 的巧克力棒,此时若 a=b,则 LYK 觉得它完成了一

codeforces 582A. GCD Table 解题报告

题目链接:http://codeforces.com/problemset/problem/582/A 网上很多题解,就不说了,直接贴代码= = 官方题解: http://codeforces.com/blog/entry/20692 1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <algorithm>

codeforces 798C.Mike and gcd problem 解题报告

题目意思:给出一个n个数序列:a1,a2,...,an (n的范围[2,100000],ax的范围[1,1e9] 然后想构造一个beautiful的序列 b1,b2, ..., bn,使得最大公约数 gcd(b1,b2,...,bn) > 1.任意ai,ai+1 可以用 ai-ai+1, ai+ai+1 来替换. 问序列 a 构造成 b 的最小操作次数 首先,这个题目是肯定有解的,也就是恒输出yes 试想一下,相邻两个数之间无非就是四种情况: (1)对于同偶情况,不需要做转换,公约数直接为2:

POJ 1905(集训比赛2B_A题)解题报告

题目链接:http://poj.org/problem?id=1905 --------------------------------------------------------- 题意:一个线段,给出长度.加热温度及热膨胀系数,线段加热后变为圆弧的一部分,要求求弧顶长度为多少. 思路:简单的画一下图,发现几何关系还是比较明确的,但是发现x的数学表达式并不容易解出来,所以采用二分法求值的方法.选择二分的对象很重要,直接选择对要求的x进行二分,避免角度误差太大. 代码: #include <

POJ 3122 (集训比赛2B_B题)解题报告

题目链接:http://poj.org/problem?id=3122 -------------------------------------------------------- 题意:每人只能从一个派里面切割,要求每个人的派的面积相等,求这个最大面积. 思路:二分法,下限是所有人从最小的里面切割,上限是所有派都完全分割.每次进行二分,判断解是否可行,通过可行性,对上下限进行调整,最终得到结果. 代码: #include <cstdio> #include <cmath> i

CodeForces 551C(集训比赛2B_C题)解题报告

题目链接:http://codeforces.com/problemset/problem/551/C --------------------------------------------------------------------------------- 题意:有n个地点,每个地点有箱子,然后有一定人数,每个人从第i个位置移动到第i+1的位置花费1S,每个人移动一个箱子花费1S,要求把所有箱子全部移除花费的最小时间是多少 思路:二分+贪心的思想,每次对一名学生进行判断.对所求时间进行

「THUSCH 2017」大魔法师 解题报告

「THUSCH 2017」大魔法师 狗体面太长,帖链接了 思路,维护一个\(1\times 4\)的答案向量表示\(A,B,C,len\),最后一个表示线段树上区间长度,然后每次的操作都有一个转移矩阵,随便搞搞就成了,卡常 Code: #include <cstdio> #include <cstring> namespace io { const int SIZE=(1<<21)+1; char ibuf[SIZE],*iS,*iT,obuf[SIZE],*oS=ob

2017 Multi-University Training 1 解题报告

Add More Zero Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 2245    Accepted Submission(s): 1053 Problem Description There is a youngster known for amateur propositions concerning several ma