BZOJ 3884 上帝与集合的正确用法
2018-02-27 20:25
274 查看
Problem
BZOJ链接洛谷链接
Solution
介绍一下扩展欧拉定理吧。ab≡abmodϕ(p)+ϕ(p)ab≡abmodϕ(p)+ϕ(p)
这个就可以解决b与p可能不互质的问题。
递归函数:
int solve(int p) { if(p==1) return 0; reutrn power(2,solve(phi[p])+phi[p],p); }
不过由于速度的原因,你可能会需要O(logn)O(logn)快速乘
int mul(int x,int y,int p) { int res=0; while(y) { if(y&1) res=((ll)res+a)%p; a=((ll)a+a)%p; y>>=1; } return res; }
不过,时间复杂度还可以更优啊,下面的方法参考了出题人大爷(PoPoQQQ)的题解:
注意到b的质因数只有2,那么将p中所有的2消去即可使其互质。
设p=2k∗q,2∤qp=2k∗q,2∤q
根据同余的同乘性:
ans=2k∗(2(b−k)modϕ(q)modq)=2k∗(2(bmodϕ(q)−kmodϕ(q)+ϕ(q))modphi(q)modϕ(q)ans=2k∗(2(b−k)modϕ(q)modq)=2k∗(2(bmodϕ(q)−kmodϕ(q)+ϕ(q))modphi(q)modϕ(q)
对于上面的bmodϕ(q)bmodϕ(q)和原来求解的式子相同,那么就可以继续递归求解,边界条件p=1时返回0。
Code
#include <iostream> #include <cstdio> using namespace std; typedef long long ll; int z,a; int phi(int x) { int i,res=x; for(int i=2;i*i<=x;i++) if(x%i==0) { res/=i;res*=i-1; while(x%i==0) x/=i; } if(x^1) res/=x,res*=x-1; return res; } int power(int x,int y,int p) { int res=1; while(y) { if(y&1) res=(ll)res*x%p; x=(ll)x*x%p; y>>=1; } return res; } int solve(int x) { if(x==1) return 0; int tmp=0; while(~x&1) x>>=1,tmp++; int p=phi(x); int res=solve(p); res+=p-tmp%p;res%=p; res=power(2,res,x)%x; return res<<tmp; } int main() { #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); #endif scanf("%d",&z); while(z--) { scanf("%d",&a); printf("%d\n",solve(a)); } return 0; }
相关文章推荐
- [题解] BZOJ 3884 上帝与集合的正确用法
- bzoj 3884 上帝与集合的正确用法 扩展欧拉定理
- Bzoj3884 上帝与集合的正确用法
- BZOJ3884 上帝与集合的正确用法(欧拉函数)
- [题解]bzoj3884 上帝与集合的正确用法
- 【BZOJ3884】【降幂大法】上帝与集合的正确用法
- bzoj千题计划264:bzoj3884: 上帝与集合的正确用法
- 【BZOJ 3884】 上帝与集合的正确用法|欧拉函数
- BZOJ 3884: 上帝与集合的正确用法
- (bzoj 3884 上帝与集合的正确用法)<欧拉定理>
- BZOJ3884 上帝与集合的正确用法
- BZOJ3884 上帝与集合的正确用法
- 【BZOJ 3884】 上帝与集合的正确用法
- BZOJ3884: 上帝与集合的正确用法
- bzoj 3884: 上帝与集合的正确用法
- [bzoj3884]上帝与集合的正确用法
- bzoj 3884: 上帝与集合的正确用法 欧拉定理+数学
- BZOJ 3884 上帝与集合的正确用法
- BZOJ 3884 上帝与集合的正确用法 欧拉定理
- BZOJ 3884 上帝与集合的正确用法