ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

川大新生杯——欧拉筛

2019-11-27 21:57:24  阅读:359  来源: 互联网

标签:prime 合数 visit 新生 川大 阶乘 include 欧拉 mod


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里面纪录的素数,升序来当做要消去合数的最小素因子。
打表观察来理解 :img

发现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\n",sum);
    }
}

标签:prime,合数,visit,新生,川大,阶乘,include,欧拉,mod
来源: https://www.cnblogs.com/IamIron-Man/p/11945709.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有