C++数论板题(弹药科技):Lengendre定理和欧拉函数
弹药科技
时间限制: 1 Sec 内存限制: 128 MB
题目描述
经过精灵族全力抵挡,精灵终于坚持到了联络系统的重建,于是精灵向人类求助,
大魔法师伊扎洛决定弓}用博士的最新科技来抗敌。 伊扎洛:“博士,还没好吗?” 博士:“只差一步了!只需要在正确的位置装上弹药就可以了!”博士的最新科技是全新的炸弹,但是现在还需要一步装弹药的操作。博士的炸弹有N!个位置可以装弹药(>.<),但是只有在正确的位置装上弹药才能启动,博士将装弹药的位置编号为1到N!,一个位置i需要装弹药,当且仅当gcd(i, N!) ≠ 1且 N! mod i ≠0,现在博士不要求你求出所有装弹药位置,只需要你求出满足要求 的位置的数量就可以了。
输入 一个数N
输出
表示满足要求的位置数量,答案对mod1000000007输出
样例输入
4
样例输出
9
提示 【数据范围】
N <= 1000000
N!为总方案数。那么题目要求的答案便是总方案数n!减去与n!互质的数与n!的所有因子。
与n!互质的数容易想到使用欧拉函数来求
其中表示把n分解成质因数的结果。
n!的因数个数也可以这么求
w为唯一分解后质数的指数。
需要注意的是,w不能直接求,需要用Lengendre定理。(这里Lengendre定理不能求模)
#include<iostream>
#include<cstdio>
using namespace std;
#define N 1000010
#define MOD 1000000007
#define LL long long
LL idx[N],prime[N],n,cnt,phi,fac=1,sum=1;
bool vis[N];
void Euler(int n) {
for(int i=2;i<=n;i++) {
if(vis[i]==0)
prime[++cnt]=i;
for(int j=1;j<=cnt && 1ll*i*prime[j]<=n;j++) {
vis[i*prime[j]]=1;
if(i%prime[j]==0) break;
}
}
}
LL LG(LL n,LL P) {
LL ans=0,sum=P;
while(n>=sum) {
ans=(ans+n/sum);
sum=sum*P;
}
return ans;
}
LL qkpow(LL base,LL indexx)
{
LL fuck=1;
while(indexx>0)
{
if(indexx&1)
fuck=fuck*base%MOD;
base=base*base%MOD;
indexx>>=1;
}
return fuck%MOD;
}
LL inv(LL sum) {
return qkpow(sum,MOD-2);
}
int main() {
cin>>n;
Euler(n);
for(int i=1;i<=n;i++)
fac=(1ll*fac*i)%MOD;
phi=fac;
for(int i=1;i<=cnt;i++) {
phi=1ll*phi*(prime[i] - 1)%MOD*inv(prime[i]) %MOD;
sum=(1ll*sum*(LG(n,prime[i])+1)%MOD)%MOD;
}
cout<<(fac-phi+MOD+MOD-sum+1)%MOD;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)