• BZOJ 4869: [Shoi2017]相逢是问候


    题目大意:

    维护一个序列,支持将区间内的数x变为c^x,区间求和。

    题解:
    扩展欧拉定理

    a^b=a^(b%phi(p)+phi(p)) ( mod p )

    然后因为底数是确定的,所以一个数最多运行log(x)次就不会变了,因为phi(p)执行log(x)次后变为1

    线段树暴力即可

    代码:

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int n,mod,c,m,p,cnt,a[1000005],phi[1000005],tree[1000005],minn[1000005];
    int get_phi(int x){
    	int ans=x;
    	for (int i=2; i*i<=x; i++)
    		if (x%i==0){
    			ans=ans/i*(i-1);
    			while (x%i==0) x/=i;
    		}
    	if (x!=1) ans=ans/x*(x-1);
    	return ans;
    }
    void build(int t,int l,int r){
    	if (l==r){
    		tree[t]=a[l];
    		return;
    	}
    	int mid=(l+r)>>1;
    	build(t<<1,l,mid);
    	build(t<<1|1,mid+1,r);
    	tree[t]=(tree[t<<1]+tree[t<<1|1])%mod;
    }
    int pow(int a,int b,int mod){
    	int ans=1;
    	while (b){
    		if (b&1) ans=1ll*ans*a%mod;
    		a=1ll*a*a%mod;
    		b=b>>1;
    	}
    	return ans;
    }
    int query(int a,int times){
    	for (int i=times; i>=1; i--){
    		if (a>=phi[i]) a=a%phi[i]+phi[i];
    		a=pow(c,a,phi[i-1]);
    		if (!a) a=phi[i-1];
    	}
    	return a;
    }
    void change(int t,int l,int r,int x,int y){
    	if (l>y || r<x) return;
    	if (minn[t]>=cnt) return;
    	if (l==r){
    		minn[t]++;
    		tree[t]=query(a[l],minn[t]);
    		return;
    	}
    	int mid=(l+r)>>1;
    	change(t<<1,l,mid,x,y);
    	change(t<<1|1,mid+1,r,x,y);
    	tree[t]=(tree[t<<1]+tree[t<<1|1])%mod;
    	minn[t]=min(minn[t<<1],minn[t<<1|1]);
    }
    int query(int t,int l,int r,int x,int y){
    	if (l>y || r<x) return 0;
    	if (l>=x && r<=y) return tree[t];
    	int mid=(l+r)>>1;
    	return (query(t<<1,l,mid,x,y)+query(t<<1|1,mid+1,r,x,y))%mod;
    }
    int main(){
    	scanf("%d%d%d%d",&n,&m,&p,&c);
    	for (int i=1; i<=n; i++)
    		scanf("%d",&a[i]);
    	mod=phi[0]=p;
    	while (p!=1){
    		phi[++cnt]=get_phi(p);
    		p=phi[cnt];
    	}
    	phi[++cnt]=1;
    	build(1,1,n);
    	while (m--){
    		int cas,l,r;
    		scanf("%d%d%d",&cas,&l,&r);
    		if (cas==0) change(1,1,n,l,r);
    		else printf("%d
    ",query(1,1,n,l,r));
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    罗杨美慧 20180912-3 词频统计
    罗杨美慧 20190912-2 命令行
    罗杨美慧 20190905-1 每周例行报告
    罗杨美慧 20190905-2 博客作业
    20190919-4 测试,结对要求
    孙晓宇-20190912-1 每周例行报告
    孙晓宇-20180912-3 词频统计
    (第二周)孙晓宇20190912-2 命令行
    孙晓宇20190905-2 博客作业
    孙晓宇20190905-1 每周例行报告
  • 原文地址:https://www.cnblogs.com/silenty/p/8921302.html
Copyright © 2020-2023  润新知