Loading [MathJax]/jax/element/mml/optable/SuppMathOperators.js

[bzoj2186][Sdoi2008]沙拉公主的困惑

来自FallDream的博客,未经允许,请勿转载,谢谢。


 

题意:T组数据,每次求[1,n!]里有多少个与m!互质的数。  T<=10000 n,m<=10^7

 

一开始想着乱容斥啥的 根本不可做...但是实际上没那么复杂。

考虑把[1,n!]按照取余m!的不同分成m!组,发现要么全都互质,要么全都不互质,所以我们只要求[1,m!]里跟m!互质的数就好了,也就是求φ(m!)

那么这样就很简单了,根据欧拉函数的一套理论(#滑稽),我们先筛出质数,然后φ(m!)=m!i1i,其中1且i是质数。

答案就是\frac{n!}{m!}\varphi(m!)

实现上还要线性求个逆元,这都很简单啦。

然后考虑R<=m的情况,貌似出题人没有考虑到或者没有写出来,虽然不判断都能过,但是直接这么算是不行的。

发现p在筛的时候会被除掉,所以在算阶乘的时候忽略它,然后在算的时候也不算它的逆元,可能就行了?

貌似好麻烦,懒得实现了。

复制代码
#include<iostream>
#include<cstdio>
#define MN 10000000
using namespace std;
inline int read()
{
    int x = 0 , f = 1; char ch = getchar();
    while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
    while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
    return x * f;
}

int s[MN+5],T,mod,f[MN+5],num=0,inv[MN+5],p[MN+5];
bool b[MN+5];

int main()
{
    T=read();mod=read();
    f[1]=1,p[0]=p[1]=inv[0]=inv[1]=1;
    for(register int i=2;i<=MN;++i)
    {
        if(!b[i]) s[++num]=i;
        for(int j=1;s[j]*i<=MN;++j)
        {
            b[s[j]*i]=1;
            if(i%s[j]==0) break;
        }
    }
    for(register int i=2;i<=MN;++i)
        p[i]=1LL*p[i-1]*i%mod,inv[i]=1LL*(mod-mod/i)*inv[mod%i]%mod;
    for(register int i=2;i<=MN;++i)
        f[i]=(b[i]?f[i-1]:(1LL*f[i-1]*(i-1)%mod*inv[i]%mod));
    for(register int i=1;i<=T;++i)
    {
        int n=read(),m=read();
        printf("%d\n",1LL*p[n]*f[m]%mod);
    }
    return 0;
}
复制代码

 

posted @   FallDream  阅读(201)  评论(0编辑  收藏  举报
编辑推荐:
· 大模型 Token 究竟是啥:图解大模型Token
· 35岁程序员的中年求职记:四次碰壁后的深度反思
· 继承的思维:从思维模式到架构设计的深度解析
· 如何在 .NET 中 使用 ANTLR4
· 后端思维之高并发处理方案
阅读排行:
· BotSharp + MCP 三步实现智能体开发
· BotSharp 5.0 MCP:迈向更开放的AI Agent框架
· 5. RabbitMQ 消息队列中 Exchanges(交换机) 的详细说明
· 【ESP32】两种模拟 USB 鼠标的方法
· 设计模式脉络
点击右上角即可分享
微信分享提示