那些需要疯狂降幂的题目(欧拉降幂,快速幂)

FZU1759 Super A^B mod C

  • 板子题,(1<=A,C<=1000000000,1<=B<=10^1000000),求 (A^B)modC 的值
  • 欧拉降幂,sqrt(c)求欧拉函数,还用到了快速幂
  • 欧拉降幂就是左边这个公式了
  • 如果AC互质的话直接用欧拉定理这个公式降幂
  • 代码
     1 #include <cstdio>
     2 #include <iostream>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <cmath>
     6 #define nmax 1000010
     7 
     8 using namespace std;
     9 typedef long long ll;
    10 char b[nmax];
    11 ll a,c,cc;
    12 
    13 ll gcd(ll x,ll y){
    14     if(y==0) return x;
    15     else return gcd(y,x%y);
    16 }
    17 
    18 ll phi(ll x){
    19     ll t=sqrt(x),ans=1,t2=x;
    20     for (ll i=2; i<=t; i++) {
    21         if(x%i) continue;
    22         t2/=i;
    23         ans*=(i-1);
    24         while(x%i==0) x/=i;
    25         if(x==1) break;
    26     }
    27     if(x>1) { ans*=(x-1); t2/=x; } //有个因数大于sqrt
    28     ans*=t2;
    29     return ans;
    30 }
    31 
    32 ll quickpow(ll x,ll y){  //x^y%c
    33     if(y==0) return 1;
    34     if(y==1) return x%c;
    35     ll t=quickpow(x,y/2);
    36     if(y%2) return (t*t%c)*x%c;
    37     else return t*t%c;
    38 }
    39 
    40 int main(){
    41     while( scanf("%I64d%s%I64d",&a,b,&c)!=EOF){
    42         ll d=gcd( max(a,c),min(a,c) );
    43         cc=phi(c);
    44         int l=strlen(b);
    45         ll t=0;//t==b%phi(c)
    46         for (int i=0; i<l; i++) {
    47             t*=10;
    48             t+=(b[i]-'0')%cc;
    49             t%=cc;
    50         }
    51         if(d==1) printf("%I64d\n",quickpow(a,t));//a^(b%phi(c))modc
    52         else{
    53             if(l<=10) {
    54                 ll nb=0;
    55                 for (int i=0; i<l; i++) { nb*=10; nb+=(b[i]-'0'); }
    56                 printf("%I64d\n",quickpow(a,nb));
    57             }else{  //a^(b%phi(c)+phi(c))modc
    58                 printf("%I64d\n",quickpow(a,t+cc));
    59             }
    60         }
    61     }
    62     return 0;
    63 }
    (╥╯^╰╥)
  • 这题提交之后编译错误不给提示。。。看看评论吧https://vjudge.net/problem/FZU-1759

 

 

BZOJ3884: 上帝与集合的正确用法

  • 跟上面一题差不多用欧拉公式降幂,只是这题可以吧2^k提出来所以如果用上题表达的话在降幂的时候AC一定互质
  • ORZ出题大佬http://blog.csdn.net/popoqqq/article/details/43951401
  • 然后本来我是根号n算的欧拉函数结果TLE了???于是乖乖欧拉筛
  • 求欧拉函数的时候最外面那层循环还是到1e7吧,,,不到的话后面的质数phi都是0 了
  • 代码:
     1 #include <bits/stdc++.h>
     2 #define nmax 1e7+5
     3  
     4 using namespace std;
     5 typedef long long ll;
     6 ll in;
     7 int cp=-1;
     8 int table[10000005]={0},pri[10000005],phi[10000005];
     9  
    10 ll getphi(){
    11     for (int i=2; i<=1e7; i++) {
    12         if(!table[i]) { pri[++cp]=i; phi[i]=i-1; }
    13         for (int j=0; j<=cp; j++) {
    14             int t=pri[j]*i;
    15             if(t>1e7) break;
    16             table[t]=1;
    17             if(i%pri[j]==0) { phi[t]=phi[i]*pri[j]; break;}
    18             phi[t]=phi[i]*(pri[j]-1);
    19         }
    20     }
    21 }
    22  
    23 inline ll mypow(ll x,ll m){  //(2^x)modm
    24     if(x==0) return 1;
    25     if(x==1) return 2;
    26     ll t=mypow(x/2,m);
    27     if(x%2) return (t*t<<1)%m;
    28     else return t*t%m;
    29 }
    30  
    31 inline ll f(ll p){//2^(inf)%p     2^k*(2^(2^inf-k)%p)
    32      if(p==1) return 0;
    33     int k=0;
    34     ll tp=p;
    35     while(!(tp&1)) { tp>>=1; k++; }
    36     ll x=f(phi[tp]);
    37     ll re=( (x-k) + abs(x-k)*phi[p] )%phi[p];  //防止x-k<0
    38      return (1<<k)*mypow(re,p)%p;
    39 }
    40  
    41 int main(){
    42     getphi();
    43      phi[1]=1;
    44     int t;
    45     cin>>t;
    46     while(t--){
    47         scanf("%lld",&in);
    48         printf("%lld\n",f(in));
    49     }
    50     return 0;
    51 }
    rp++++++

     

posted @ 2019-09-01 15:04  连昵称都不能重复  阅读(455)  评论(0编辑  收藏  举报