您的位置:首页 > 其它

欧拉定理 BZOJ 3884 上帝与集合的正确用法

2017-06-06 15:05 295 查看

BZOJ 3884 上帝与集合的正确用法

出题人的题解如下







辣鸡的我,并看不懂,所以经过漫长的分析,在此辣鸡的赘述一下。注,以下所有a^b均表示a的b次方。

有欧拉定理


这道题里面指数太大了,所以我们考虑在mod的意义下,用欧拉定理降指数。因为欧拉定理的条件是a,n互质,所以第一步我们要使mod变成一个奇数,由于任何的p都可以拆成2^k* 奇数q。我们把式子提出一个2^k,然后就可以用欧拉定理了。指数x可以拆成p* phi(q)+r,2^x=2^phi(q)^p* 2^r,在mod的意义下,2^phi(q)=1,所以2^x=2^r=2^(x%phi(q))。递归到q=0。

这里计算phi用的是sqrt的方法,依据是欧拉函数的一个公式:由唯一分解定理得x=p1^x1 * p2^x2 * p3^x3 * … * pn^xn(p为质数),phi(x)=x*(1-1/p1)(1-1/p2)(1-1/p3)…(1-1/pn)。这个式子其实可以用容斥证明,分析式子可得,打开括号以后,形似x(1-1/p1-1/p2-1/p3……+1/p1p2+1/p1p3+1/p1p4…+1/p2p3+1/p2p4+1/p2p5…+1/p3p4+1/p3p5+1/p3p6……-1/p1p2p3-1/p1p2p4-1/p1p2p5…-1/p1p3p4-1/p1p3p5-1/p1p3p6…-1/p2p3p4-1/p2p3p5-1/p2p3p6……)也就是说最开始认为x个数都满足,再减去p1的倍数,p2的倍数,p3的倍数…因为减重了一部分,所以再加上p1p2的倍数,p1p3的倍数,p1p4的倍数…p2p3的倍数,p2p4的倍数…p3p4的倍数,p3p5的倍数…简述就是1-1/p+1/pp-1/ppp+1/pppp……

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define M 10001000
using namespace std;

int phi[M],prime[1001001],tot;
bool not_prime[M];

int Phi(int x){
int rt = x;
for(int i=2; i*i<=x; i++)
if(x % i == 0){
rt /= i; rt *= i-1;
while(x % i == 0)
x /= i;
}
if(x ^ 1) rt /= x, rt *= x-1;//最后还剩的话(x > 1)就加上
return rt;
}

int power(LL x, int y, int p){//这里的x,累乘会爆int
LL rt = 1;
while( y ){
if(y & 1) (rt *= x) %= p;
(x *= x) %= p; y >>= 1;
}
return rt;
}

int work(int p){
if(p == 1) return 0;
int cc = 0;
for( p; !(p&1); p>>=1, ++cc);//提出2^k
int phi = Phi(p);
int rt = work( phi );
(rt += phi - cc % phi ) %= phi;
rt = power(2, rt, p) % p;
return rt << cc;//乘上2^k
}

int main(){
int T, p;
for(cin>>T; T; T--){
scanf("%d", &p);
printf("%d\n", work(p));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: