[bzoj2186][Sdoi2008]沙拉公主的困惑
来自FallDream的博客,未经允许,请勿转载,谢谢。
题意:T组数据,每次求[1,n!]里有多少个与m!互质的数。 T<=10000 n,m<=10^7
一开始想着乱容斥啥的 根本不可做...但是实际上没那么复杂。
考虑把[1,n!]按照取余m!的不同分成m!组,发现要么全都互质,要么全都不互质,所以我们只要求[1,m!]里跟m!互质的数就好了,也就是求φ(m!)
那么这样就很简单了,根据欧拉函数的一套理论(#滑稽),我们先筛出质数,然后φ(m!)=m!∗∏i−1i,其中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; }
FallDream代表秋之国向您问好!
欢迎您来我的博客www.cnblogs.com/FallDream
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 大模型 Token 究竟是啥:图解大模型Token
· 35岁程序员的中年求职记:四次碰壁后的深度反思
· 继承的思维:从思维模式到架构设计的深度解析
· 如何在 .NET 中 使用 ANTLR4
· 后端思维之高并发处理方案
· BotSharp + MCP 三步实现智能体开发
· BotSharp 5.0 MCP:迈向更开放的AI Agent框架
· 5. RabbitMQ 消息队列中 Exchanges(交换机) 的详细说明
· 【ESP32】两种模拟 USB 鼠标的方法
· 设计模式脉络