川大新生杯——欧拉筛
Posted iamiron-man
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了川大新生杯——欧拉筛相关的知识,希望对你有一定的参考价值。
mod的一些性质
(a mod n) (b mod n)=(ab) mod n
((a mod n)(b mod n)) mod n=(ab) mod n
如果a≡b(mod m),x≡y(mod m),则a+x≡b+y(mod m)。
如果a≡b(mod m),x≡y(mod m),则ax≡by(mod m)。
如果ac≡bc(mod m),且c和m互质,则a≡b(mod m) (就是说同余式两边可以同时除以一个和模数互质的数)。
川大新生杯——模板筛
lglg最近爱上了炒股,他想在股票市场内买一些股票。
现在有编号为1,2,3,...,100000000的100000000支股票,每个股票的价值等于其编号的阶乘(例如编号为5的股票的价值就是120)。
lglg是一个很挑剔的人,他只喜欢编号为质数的股票,但他很有钱,因此他希望买下所有编号小于等于N(1<=N<=1e8)并且编号为质数的股票,请你帮他算一算这些股票的价值之和。
由于价值和很大,他希望你能告诉他价值之和对P(1e3<=P<=1e5)取模后的值。
输入描述:
输入包含多组数据 第一行是一个正整数 T(1<=T<=1000),代表数据的组数。每组数据只有一行,包含两个正整数 N 和 P 数字之间用空格隔开,其代表的含义及范围已在题面中给出。
输出描述:
每组数据输出一行,表示lglg希望买下的所有股票的价值之和对P取模后的值
示例1
输入
2
5 1001
20 1001
输出
128
86
欧拉筛和mod的运用能让跑起来贼快。
mod:
1、阶乘的时候比mod的数大了肯定就永远是零了,不用算了,所以比P大的肯定是零了,阶乘和对p取余,那阶乘对P取余岂不是更满足了,所以欧拉筛只要筛1e5以下的就行,不用1e8
2、每个组数据只算算一遍阶乘,遇到素数就算和,不是素数不算,但阶乘(和mod)还在跑,循环结尾到n,要是到mod的p了也不用跑了,后面必定已经都零了
欧拉筛:打表从2筛到需要的最大,每个合数被它的最小质因子筛出去,prime【0】用来存储一共多少,对于visit[i*prime[j]] = 1 的解释: 这里不是用i的倍数来消去合数,而是把 prime里面纪录的素数,升序来当做要消去合数的最小素因子。
打表观察来理解 :发现i在消去合数中的作用是当做倍数的。
对于 i%prime[j] == 0 就break的解释 :当 i是prime[j]的倍数时,i = kprime[j],如果继续运算 j+1,i * prime[j+1] = prime[j] * k prime[j+1],这里prime[j]是最小的素因子,当i = k * prime[j+1]时会重复,所以才跳出循环。
举个例子 :i = 8 ,j = 1,prime[j] = 2,如果不跳出循环,prime[j+1] = 3,8 * 3 = 2 * 4 * 3 = 2 * 12,在i = 12时会计算。因为欧拉筛法的原理便是通过最小素因子来消除。
————————————————
版权声明:本文为CSDN博主「彤云望月」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_39763472/article/details/82428602
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
bool visit[100010];
int prime[100010];
void oulashai()
{
memset(visit,0,sizeof(visit));
for (int i=2;i<=100000;i++)
{
if (!visit[i])
prime[++prime[0]]=i;
for (int j=1;j<=prime[0] and i*prime[j]<=100000;j++)
{
visit[i*prime[j]]=1;
if (i%prime[j]==0)
break;
}
}
}
int main()
{
// freopen("test.in","r",stdin);
// freopen("test.out","w",stdout);
int t,n,p;
oulashai();
cin>>t;
for (int i=1;i<=t;i++)
{
long long sum=0,jc=1;
scanf("%d%d",&n,&p);
for (int j=2;j<=min(n,p);j++)
{
jc=(jc*j)%p;
if (!visit[j])
sum=(sum+jc)%p;
}
printf("%lld
",sum);
}
}
以上是关于川大新生杯——欧拉筛的主要内容,如果未能解决你的问题,请参考以下文章