标签:10 函数 筛法 签到 质数 int P3601 欧拉
一、前导知识
二、朴素思路
我们先不管数据范围是不是\(10^{12}\),先思考就朴素的作法是什么样的:
\(qiandao(x)=x−ϕ(x)\) ,假设\(x\)在我们可控的数据范围内,就是筛出数据范围内的\(ϕ(x)\), 然后利用公式计算一下\(sum\)和,再\(mod\)一下就行。
这样做的知识点就是欧拉函数的筛法,直接套模板就行。
数据样例的说明:
1、数据范围 60% l,\(r<=10^7\)
2、数据范围 100% l,\(r<=10^{12}\)
所以,不出意外,上面的朴素作法,只能过掉\(10^7\)的数据,就是PASS掉\(6\)个测试点,得了\(60\)分,无法\(AC\)掉本题。
但不管怎样,这是这道题最本质的作法,是最应该第一步想到的,是没有更好办法的情况下的最优解,这是前进路上的必经之路。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
//左右边界
LL l, r;
int ans;//答案
const int N = 1e8 + 10;
const int MOD = 666623333;
int primes[N]; //保存的是每一个质数
int cnt; //cnt代表质数下标,就是到第几个了
int phi[N]; //欧拉函数值
bool st[N]; //是不是已经被筛掉了
// 求1-N之间每一个数的欧拉函数
// 线性筛法求质数的过程当中,捎带着求出每个数的欧拉函数值,其实还可以顺便求出很多东西。
void get_eulers(int n) {
phi[1] = 1;
for (int i = 2; i <= n; i++) {
if (!st[i]) {
primes[cnt++] = i;
phi[i] = i - 1;
}
for (int j = 0; primes[j] <= n / i; j++) {
int t = primes[j] * i;
st[t] = true;
if (i % primes[j] == 0) {
phi[t] = phi[i] * primes[j];
break;
} else {
phi[t] = phi[i] * (primes[j] - 1);
}
}
}
}
int main() {
//1、读入
scanf("%lld%lld", &l, &r);
//2、大力出奇迹!线性筛欧拉函数
get_eulers(r);
//3、qiandao(x)=x−ϕ(x),计算sum,再取一下模
for (LL i = l; i <= r; i++) ans = (ans + i - phi[i]) % MOD;
//4、输出答案
printf("%d\n", ans);
return 0;
}
标签:10,函数,筛法,签到,质数,int,P3601,欧拉 来源: https://www.cnblogs.com/littlehb/p/15213660.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。