zoukankan      html  css  js  c++  java
  • [六省联考2017]相逢是问候

    description

    洛谷

    solution

    首先你要知道扩展欧拉定理。

    扩展欧拉定理

    [a^cequiv egin{cases} a^{c\%phi(p)}~~~~~~~~~~~gcd(a,p)=1\ a^c~~~~~~~~~~~~~~~~~~gcd(a,p) eq1,b<phi(p)\ a^{c\%phi(p)+phi(p)}~~~~gcd(a,p) eq1,cgeqphi(p) end{cases}~~~~~~~(mod~p) ]

    可能不太靠谱的证明:
    考虑(a)为质数的情况。
    (p=p'a^r),则(gcd(a,p')=1);由欧拉定理,(a^{phi(p')}equiv 1(mod p'));
    而易知(phi(p')|phi(p)),因此(a^{phi(p)}equiv 1(mod p'));
    那么(a^{phi(p)}=k imes p'+1)
    两边同乘(a^r),得(a^{phi(p)+r}=k imes p+a^r)
    因此(a^{phi(p)+r}equiv a^r(mod p))
    (rle phi(p),)所以对于任意(cgephi(p)ge r),(a^{phi(p)+c}equiv a^c(mod p))
    对于质数的幂:
    ((a^k)^cequiv a^{kc}equiv a^{k(phi(p)+c)}equiv (a^k)^{phi(p)+c}(mod p),cge phi(p))
    对于所有的(a),分解质因数即可。

    而我们知道一个数取至少(log+1)(phi)后会变成(1).
    因此我们暴力修改,直到后面的(phi)变成(1)后剪枝即可。
    需要注意的是在(phi)变成(1)后一定要再多取一次。

    这样的复杂度...
    我们考察一个数,算上快速幂的(log),它被修改一次的复杂度是(log^2)的,要修改(log)次,
    所以每个数应该是(log^3)?不是很会证复杂度
    然后常数大一点就会像我一样(T)

    于是我们把快速幂分块预处理一波,复杂度就变成了(log^2)
    还是挺神仙的

    Code

    #include<bits/stdc++.h>
    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<iomanip>
    #include<cstring>
    #include<complex>
    #include<vector>
    #include<cstdio>
    #include<string>
    #include<bitset>
    #include<ctime>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<map>
    #include<set>
    #define Cpy(x,y) memcpy(x,y,sizeof(x))
    #define Set(x,y) memset(x,y,sizeof(x))
    #define FILE "4869"
    #define mp make_pair
    #define pb push_back
    #define RG register
    #define il inline
    using namespace std;
    typedef unsigned long long ull;
    typedef vector<int>VI;
    typedef long long ll;
    typedef double dd;
    const int N=50010;
    const int M=1000010;
    const dd eps=1e-5;
    const int inf=2147483647;
    const ll INF=1ll<<60;
    const ll P=100000;
    il ll read(){
      RG ll data=0,w=1;RG char ch=getchar();
      while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
      if(ch=='-')w=-1,ch=getchar();
      while(ch<='9'&&ch>='0')data=data*10+ch-48,ch=getchar();
      return data*w;
    }
    
    il void file(){
      srand(time(NULL)+rand());
      freopen(FILE".in","r",stdin);
      freopen(FILE".out","w",stdout);
    }
    
    int n,m,p,c,cal[N],top,a[N];
    il int getphi(int x){
      RG int phi=x;
      for(RG int i=2;1ll*i*i<=x;i++)
        if(x%i==0){phi=phi/i*(i-1);while(x%i==0)x/=i;}
      if(x!=1)phi=phi/x*(x-1);return phi;
    }
    il int poww(int a,int b,int mod){
      RG int ret=1;bool pda=0,pdret=0;
      while(b){
        if(b&1){
          if(pda||1ll*ret*a>=mod)pdret=1;
          ret=1ll*ret*a%mod;
        }
        b>>=1;
        if(1ll*a*a>=mod)pda=1;
        a=1ll*a*a%mod;
      }
      return ret+pdret*mod;
    }
    
    int listc[10005][52],listt[10005][52];
    
    int sum[N<<2],cover[N<<2];
    #define ls (i<<1)
    #define rs (i<<1|1)
    #define mid ((l+r)>>1)
    il void update(int i){
      sum[i]=(sum[ls]+sum[rs])%p;
      cover[i]=min(cover[ls],cover[rs]);
    }
    il void build(int i,int l,int r){
      if(l==r){a[l]=sum[i]=read();cover[i]=0;return;}
      build(ls,l,mid);build(rs,mid+1,r);update(i);
    }
    int query(int i,int l,int r,int x,int y){
      if(x<=l&&r<=y)return sum[i];RG int s=0;
      if(x<=mid)s=(s+query(ls,l,mid,x,y))%p;
      if(mid<y)s=(s+query(rs,mid+1,r,x,y))%p;
      return s;
    }
    void modify(int i,int l,int r,int x,int y){
      if(cover[i]==top-1)return;
      if(l==r){
        cover[i]++;
        sum[i]=a[l]%cal[cover[i]+1]+(a[l]>=cal[cover[i]+1])*cal[cover[i]+1];
        for(RG int t=cover[i];t;t--){
          if(listc[sum[i]%10000][t]>=cal[t]||listt[sum[i]/10000][t]>=cal[t])
    	sum[i]=1ll*listc[sum[i]%10000][t]*listt[sum[i]/10000][t]%cal[t]+cal[t];
          else sum[i]=1ll*listc[sum[i]%10000][t]*listt[sum[i]/10000][t]%cal[t];
        }
        sum[i]%=p;
        return;
      }
      if(x<=mid)modify(ls,l,mid,x,y);
      if(mid<y)modify(rs,mid+1,r,x,y);
      update(i);
    }
    
    int main()
    {
      n=read();m=read();p=read();c=read();
      cal[++top]=p;
      while(cal[top]!=1){
        RG int x=getphi(cal[top]);
        cal[++top]=x;
      }
      cal[++top]=1;
    
      for(RG int i=1,ret;i<=top;i++){
        for(RG int j=0;j<10000;j++)
          listc[j][i]=poww(c,j,cal[i]);
        ret=poww(c,10000,cal[i]);
        for(RG int j=0;j<10000;j++)
          listt[j][i]=poww(ret,j,cal[i]);
      }
      
      build(1,1,n);
      for(RG int i=1,opt,l,r;i<=m;i++){
        opt=read();l=read();r=read();
        if(!opt)modify(1,1,n,l,r);
        else printf("%d
    ",query(1,1,n,l,r));
      }
      return 0;
    }
    
    
    
  • 相关阅读:
    【Nginx】跨域配置
    【Python】【Chart】图标绘制/地图生成
    【Python】操作压缩文件
    【VSCode】koroFileHeader插件自动添加文件及函数注释
    【性能】web页面性能之lighthouse使用
    【VSCode】格式化后换行
    【Python】MD5
    【IDEA】自定义/自动生成/注释/新增文件自动生成注释/自动生成方法注释
    【Java】文件下载/下载Excel/下载文件到本地
    【杂项】英语学习
  • 原文地址:https://www.cnblogs.com/cjfdf/p/9702865.html
Copyright © 2011-2022 走看看