# 小学扩展欧拉定理

-bzoj3884:上帝与集合的正确用法

#include <cstdio>
#include <cstring>
#include <algorithm>
typedef long long LL;
inline int Pow(int x,int y,int P){
int ret=1;
while(y){
if(y&1)ret=(LL)ret*x%P;
x=(LL)x*x%P,y>>=1;
}
return ret;
}
inline int Phi(int x){
if(x==1)return 1;
int i,ret=x;
for(i=2;i*i<=x;++i)
if(x%i==0){
ret=ret/i*(i-1);
while(x%i==0)x/=i;
}
if(x!=1)ret=ret/x*(x-1);
return ret;
}
inline int Power(int P){
if(P==1)return 0;
int phi=Phi(P);
return Pow(2,Power(phi)+phi,P);
}
int main(){
int T,P;
scanf("%d",&T);
while(T--){
scanf("%d",&P);
printf("%d\n",Power(P));
}
return 0;
}
Kod

-bzoj4869:[Shoi2017]相逢是问候
https://blog.sengxian.com/solutions/bzoj-4869

#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
typedef long long LL;
const int A=50;
const int N=50010;
const int F=1<<15;
const int oo=100000000;
int n,m,k,P,cmp,hp,phi[A],a[N],mi1[A][F+10],mi2[A][F+10];
inline int Pow(int x,int y,int P,int cur){
int ret=(LL)mi1[cur][y&(F-1)]*mi2[cur][y>>15]%P;
return ret;
}
inline int Pow_(int x,int y,int P,int cur){
if(y>=cmp)return Pow(x,y,P,cur);
LL ret=1;
int i;
for(i=1;i<=y;++i){
ret*=x;
if(ret>=P)return Pow(x,y,P,cur);
}
return ret+oo;
}
inline int Phi(int x){
if(x==1)return 1;
int i,ret=x;
for(i=2;i*i<=x;++i)
if(x%i==0){
ret=ret/i*(i-1);
while(x%i==0)x/=i;
}
if(x!=1)ret=ret/x*(x-1);
return ret;
}
inline int Power(int rest,int aim,int P,int cur){
if(!rest)return aim<P?aim+oo:aim%P;
int ret=Power(rest-1,aim,phi[cur+1],cur+1);
if(ret<oo)return Pow(k,ret+phi[cur+1],P,cur);
return Pow_(k,ret-oo,P,cur);
}
struct Segment_Tree{
Segment_Tree *ch[2];
int hp,sum;
inline void pushup(){
sum=(ch[0]->sum+ch[1]->sum)%P;
hp=ch[0]->hp+ch[1]->hp;
}
}*root,node[N<<2];
int sz;
#define newnode (node+(sz++))
#define mid ((l+r)>>1)
inline void build(Segment_Tree *&p,int l,int r){
p=newnode;
if(l==r){
p->hp=hp;
p->sum=a[l];
return;
}
build(p->ch[0],l,mid);
build(p->ch[1],mid+1,r);
p->pushup();
}
inline void dfs(Segment_Tree *p,int l,int r){
if(!p->hp)return;
if(l==r){
--p->hp;
p->sum=k==1?1:Power(hp-p->hp,a[l],P,0);
if(p->sum>=oo)p->sum-=oo;
return;
}
dfs(p->ch[0],l,mid);
dfs(p->ch[1],mid+1,r);
p->pushup();
}
inline void update(Segment_Tree *p,int l,int r,int z,int y){
if(z<=l&&r<=y){
dfs(p,l,r);
return;
}
if(z<=mid)update(p->ch[0],l,mid,z,y);
if(mid<y)update(p->ch[1],mid+1,r,z,y);
p->pushup();
}
inline int query(Segment_Tree *p,int l,int r,int z,int y){
if(z<=l&&r<=y)return p->sum;
int ret=0;
if(z<=mid)ret+=query(p->ch[0],l,mid,z,y);
if(mid<y)ret+=query(p->ch[1],mid+1,r,z,y);
return ret%P;
}
inline void Init(){
scanf("%d%d%d%d",&n,&m,&P,&k);
int cur=P,step=-1,i,j;
while(true){
phi[++step]=cur;
if(cur==1)break;
cur=Phi(cur);
}
hp=step;
phi[++hp]=1;
for(i=0;i<=hp;++i){
mi1[i][0]=1%phi[i];
for(j=1;j<F;++j)
mi1[i][j]=(LL)mi1[i][j-1]*k%phi[i];
cur=(LL)mi1[i][F-1]*k%phi[i];
mi2[i][0]=1%phi[i];
for(j=1;j<F;++j)
mi2[i][j]=(LL)mi2[i][j-1]*cur%phi[i];
}
cmp=k==1?0:std::ceil(std::log(P)/std::log(k));
for(i=1;i<=n;++i)
scanf("%d",&a[i]);
build(root,1,n);
}
inline void Work(){
int opt,l,r;
while(m--){
scanf("%d%d%d",&opt,&l,&r);
if(opt){
printf("%d\n",query(root,1,n,l,r));
continue;
}
update(root,1,n,l,r);
}
}
int main(){
Init();
Work();
return 0;
}
Kod

posted @ 2018-04-10 19:03  TS_Hugh  阅读(374)  评论(0编辑  收藏