您的位置:首页 > 其它

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: