洛谷 P2155 BZOJ 2186 codevs 2301 [SDOI2008]沙拉公主的困惑

简介: 题目描述 大富翁国因为通货膨胀,以及假钞泛滥,政府决定推出一项新的政策:现有钞票编号范围为1到N的阶乘,但是,政府只发行编号与M!互质的钞票。房地产第一大户沙拉公主决定预测一下大富翁国现在所有真钞票的数量。

题目描述

大富翁国因为通货膨胀,以及假钞泛滥,政府决定推出一项新的政策:现有钞票编号范围为1到N的阶乘,但是,政府只发行编号与M!互质的钞票。房地产第一大户沙拉公主决定预测一下大富翁国现在所有真钞票的数量。现在,请你帮助沙拉公主解决这个问题,由于可能张数非常大,你只需计算出对R取模后的答案即可。R是一个质数。//codevs这里有坑,R是合数

输入输出格式

输入格式:

 

第一行为两个整数T,R。R<=10^9+10,T<=10000,表示该组中测试数据数目,R为模 后面T行,每行一对整数N,M,见题目描述 m<=n

 

输出格式:

 

共T行,对于每一对N,M,输出1至N!中与M!素质的数的数量对R取模后的值

 

输入输出样例

输入样例#1:
1 11
4 2
输出样例#1:
1

数据范围:
对于100%的数据,1 < = N , M < = 10000000

解题思路

  http://www.cnblogs.com/yangyaojia/p/6434611.html

  http://blog.csdn.net/loi_dqs/article/details/50520309

吐槽

  这题一题能抵三题做了。

  不想被卡常就离线吧,筛法筛到最大的n即可,否则卡常、卡内存太严重了,我的好不容易洛谷ac,跑了6s。

  求逆元可以线性递推,也可以扩欧。

  popoqqq大神博客的代码(https://www.luogu.org/record/show?rid=2565704)、黄学长博客(https://www.luogu.org/record/show?rid=2565713)里线性递推逆元的代码都在洛谷爆零,不知为啥。

  我的代码离线int会溢出,估计是筛法出问题,还不够优化,于是递推求逆元的数组开不下了,就用扩欧吧。

  卡一波常1.3s跑完(BZOJ不开O2跑了2.9s)。

源代码

6s的,求逆元用线性递推(BZOJ TLE)

#include<cstdio>
#include<cstring>
#include<algorithm>
int T,R,n,m;
long long  jc[10000010]={0};//阶乘取模
long long inv[10000010]={0};//逆元
bool not_prime[10000010]={0};//筛子
long long ans[10000010]={0};//pi累乘

void init()
{
    inv[1]=1;
    for(int i=2;i<=10000000&&i<R;i++)
        inv[i]=(R-R/i)%R*inv[R%i]%R;
    ans[1]=1;jc[1]=1;
    for(int i=2;i<=10000000;i++)
    {
        jc[i]=jc[i-1]*i%R;
        if(!not_prime[i])
        {
            ans[i]=ans[i-1]*(i-1)%R*inv[i%R]%R;
            for(int j=i<<1;j<=10000000;j+=i)
                not_prime[j]=1;
        }
        else
            ans[i]=ans[i-1];
    }
}

int main()
{
    scanf("%d%d",&T,&R);
    init();
    while(T--)
    {
        scanf("%d%d",&n,&m);
        printf("%lld\n",(long long)(jc[n])*(long long)(ans[m])%R);
    }
    return 0;
}

1.3s的,求逆元用扩欧

#include<cstdio>
#include<algorithm>
int T,R,maxn=-1;
long long  jc[10000010]={0};//阶乘取模
//int inv[10000010]={0};//逆元
bool not_prime[10000010]={0};//筛子
long long ans[10000010]={0};//pi累乘
int n[10000010]={0},m[10000010]={0};


void exgcd(int a,int b,int &x,int &y)
{
    if(b==0){x=1;y=0;return;}
    exgcd(b,a%b,x,y);
    int t=x;x=y;y=t-a/b*y;
}
inline int getine(int t)
{
    int x,y;
    exgcd(t,R,x,y);
    return (x%R+R)%R;
}//扩欧求逆元

inline void Read(int &in){
    static char ch;
    for(ch=getchar();ch>'9'||ch<'0';ch=getchar()) ;
    for(in=0;ch>='0'&&ch<='9';ch=getchar()) in=in*10+ch-'0';
}
void init()
{
    /*inv[1]=1;
    for(int i=2;i<=maxn&&i<R;i++)
        inv[i]=(R-R/i)%R*inv[R%i]%R;*///线性递推求逆元
    ans[1]=1;jc[1]=1;
    for(int i=2;i<=maxn;i++)
    {
        jc[i]=jc[i-1]*i%R;
        if(!not_prime[i])
        {
            ans[i]=ans[i-1]*(i-1)%R*getine(i%R)%R;
            for(int j=i<<1;j<=maxn;j+=i)
                not_prime[j]=1;
        }
        else
            ans[i]=ans[i-1];
    }
}

int main()
{
    Read(T);Read(R);
    for(register int i=1;i<=T;i++)
         Read(n[i]),Read(m[i]),maxn=std::max(maxn,n[i]);
    init();
    for(register int i=1;i<=T;i++)
        printf("%lld\n",jc[n[i]]*ans[m[i]]%R);
    return 0;
}

洛谷记录里最优的代码,用户ID小小莫。Orz,洛谷跑了0.9s,BZOJ不开O2跑了2.6s,素数筛法值得学习。

#include <cstdio>
#include <algorithm>
using namespace std;
static const int maxm = 10000 + 50;
static const int maxx = 10000000 + 50;
typedef long long LL;
bool Notprime[maxx];
int inv[maxx],phi[maxx],fac[maxx],prime[maxx];
int T,n[maxm],m[maxm],p,cnt,tot;

void Read(int &);

inline void Linear_shaker(){
    int maxn = tot+1;
    fac[1]=1;inv[1]=1;phi[1]=1;
    for(register int i=2;i<maxn;i++){
        if(!Notprime[i])
            prime[++cnt]=i;
        for(register int j=1;j<=cnt && i*prime[j]<maxn;j++){
            Notprime[i*prime[j]]=1;
            if(i%prime[j]==0) break;
        }
    }
    for(register int i=2;i<=maxn;i++){
        fac[i] = ((LL)fac[i-1]*i)%p;
        if(i<p) inv[i] = (LL)(p-p/i)*inv[p%i]%p;
        if(!Notprime[i]) phi[i] = (LL)phi[i-1]*(i-1)%p*inv[i%p]%p;
        else phi[i] = phi[i-1];
    }
}
int main(){
    Read(T),Read(p);
    for(register int i=1;i<=T;i++) Read(n[i]),Read(m[i]),tot = max(tot,n[i]);
    Linear_shaker();
    for(register int i=1;i<=T;i++)
        printf("%lld\n",(LL)fac[n[i]]*phi[m[i]]%p);
    return 0;
}

void Read(int &in){
    static char ch;
    for(ch=getchar();ch>'9'||ch<'0';ch=getchar()) ;
    for(in=0;ch>='0'&&ch<='9';ch=getchar()) in=in*10+ch-'0';
}

 

目录
相关文章
|
算法 C语言 C++
LeetCode 每日一题2347. 最好的扑克手牌
给你一个整数数组 ranks 和一个字符数组 suit 。你有 5 张扑克牌,第 i 张牌大小
92 0
|
机器学习/深度学习 人工智能 算法
LeetCode 周赛 345(2023/05/14)体验一题多解的算法之美
大家好,我是小彭。这场周赛是 LeetCode 第 345 场单周赛,整体难度不高,我们使用一题多解的方式强化练习。
140 0
|
机器学习/深度学习
【蓝桥杯集训·每日一题】 AcWing 3996. 涂色
文章目录 一、题目 1、原题链接 2、题目描述 二、解题报告 1、思路分析 2、时间复杂度 3、代码详解 三、知识风暴 区间DP Unique函数
127 0
|
存储 机器学习/深度学习 人工智能
【蓝桥杯集训·周赛】AcWing 第94场周赛
文章目录 第一题 AcWing 4870. 装物品 一、题目 1、原题链接 2、题目描述 二、解题报告 1、思路分析 2、时间复杂度 3、代码详解 第二题 AcWing 4871. 最早时刻 一、题目 1、原题链接 2、题目描述 二、解题报告 1、思路分析 2、时间复杂度 3、代码详解 第三题 AcWing 4872. 最短路之和 一、题目 1、原题链接 2、题目描述 二、解题报告 1、思路分析 2、时间复杂度 3、代码详解
83 0
|
存储 机器学习/深度学习 人工智能
【蓝桥杯集训·周赛】AcWing 第 95 场周赛
文章目录 第一题 AcWing 4873. 简单计算 一、题目 1、原题链接 2、题目描述 二、解题报告 1、思路分析 2、时间复杂度 3、代码详解 第二题 AcWing 4874. 约数 一、题目 1、原题链接 2、题目描述 二、解题报告 1、思路分析 2、时间复杂度 3、代码详解 第三题 AcWing 4875. 整数游戏 一、题目 1、原题链接 2、题目描述 二、解题报告 1、思路分析 2、时间复杂度 3、代码详解
121 0
|
存储 人工智能 算法
【蓝桥杯集训·最后一次周赛】AcWing 第 97 场周赛
文章目录 第一题 AcWing 4944. 热身计算 一、题目 1、原题链接 2、题目描述 二、解题报告 1、思路分析 2、时间复杂度 3、代码详解 第二题 AcWing 4945. 比大小 一、题目 1、原题链接 2、题目描述 二、解题报告 1、思路分析 2、时间复杂度 3、代码详解 第三题 AcWing 4946. 叶子节点 一、题目 1、原题链接 2、题目描述 二、解题报告 1、思路分析 2、时间复杂度 3、代码详解
137 0
|
JavaScript BI
【蓝桥杯集训·周赛】AcWing 第96场周赛
文章目录 第一题 AcWing 4876. 完美数 一、题目 1、原题链接 2、题目描述 二、解题报告 1、思路分析 2、时间复杂度 3、代码详解 第二题 AcWing 4877. 最大价值 一、题目 1、原题链接 2、题目描述 二、解题报告 1、思路分析 2、时间复杂度 3、代码详解 第三题 AcWing 4878. 维护数组 一、题目 1、原题链接 2、题目描述 二、解题报告 1、思路分析 2、时间复杂度 3、代码详解
93 0
|
存储 算法 C++
【蓝桥杯集训·每日一题】AcWing 2058. 笨拙的手指
文章目录 一、题目 1、原题链接 2、题目描述 二、解题报告 1、思路分析 2、时间复杂度 3、代码详解 三、知识风暴 哈希表 秦九韶算法
171 0
|
存储
【蓝桥杯集训·每日一题】AcWing 3777. 砖块
文章目录 一、题目 1、原题链接 2、题目描述 二、解题报告 1、思路分析 2、时间复杂度 3、代码详解 三、知识风暴 递推
116 0
|
存储 人工智能
【蓝桥杯集训·周赛】AcWing 第93场周赛
文章目录 第一题 AcWing 4867. 整除数 一、题目 1、原题链接 2、题目描述 二、解题报告 1、思路分析 2、时间复杂度 3、代码详解 第二题 AcWing 4868. 数字替换 一、题目 1、原题链接 2、题目描述 二、解题报告 1、思路分析 2、时间复杂度 3、代码详解 第三题 AcWing 4869. 异或值 一、题目 1、原题链接 2、题目描述 二、解题报告 1、思路分析 2、时间复杂度 3、代码详解
107 0