【洛谷】 上帝与集合的正确用法 4139

第一眼看到认为十分莽

ZZ地认为需要挨着挨着算,还要用快速幂

传送门 

不用分析题意了,Ans=2^(无穷)% p。

扩展欧拉定理:

           a ^ ( b % \varphi ( p ) )                            gcd ( a , p ) == 1                                   ( mod  p ) ……………………1

a ^ b \equiv a ^b                                                  b < \varphi ( p )                                            ( mod  p ) ……………………2

              a ^ ( b % \varphi ( p ) + phi ( p ) )           gcd ( a , p ) != 1 , b >= \varphi ( p )             ( mod  p ) ……………………3

本人不知道怎么证明!!!

根据欧拉定理:a ^ \varphi (p) \equiv 1 ( mod  p )

那么其实可以对于式子1乘上a ^ phi (p),由于a ^ phi (p) \equiv 1 ( mod  p ),所以相当于同余式子同时乘上了1,所以式子1可以划归为 a ^ b \equiv a ^ ( b % \varphi ( p ) + \varphi ( p ) ),又因为 inf 永远大于 \varphi ( p ) , 所以 3 式恒成立,所以不论 p 和 b 的关系如何,都可以表示:

a ^ b \equiv a ^ ( b % \varphi ( p ) + \varphi ( p ) )

所以,我们首先可以将题目的那个特别大的式子化简成一个较简单的式子:

2 ^ ( 2 ^ ( …… ) % \varphi ( p ) + \varphi ( p ) ) % p 

接着我们又可以对 2 ^ ( 2 ^ ( …… ) % \varphi ( p ) + \varphi ( p ) ) % p 中 2 ^ ( …… ) 做同样的工作;

这样是不是可以递归处理了?

边界条件是:p == 1 时,\varphi ( p ) = 1 , 任意数 % 1 都是 0 ,所以 return  1 --- ( Inf % \varphi ( 1 ) = 0 , \varphi ( 1 ) = 1 ) 就好了!

AC 代码:

#include <bits/stdc++.h>

const  int  N = 1e7 + 10 ;

int  phi [ N ] , prime [ N ] ;
int  T ;
long long  p ;
bool  vis [ N ] ;

long long  pow ( long long  a , long long  b , long long  mod ) {
    long long  res = 1 ;
    for ( ; b ; b >>= 1 , a = ( a * a ) % mod )
        if ( b & 1 )
            res = ( res * a ) % mod ;
    return  res % mod ;
}

long long  dfs ( long long  x ) {
    if ( x == 1 )  return  1 ;
    long long  tmp = pow ( 2 , dfs ( 1ll * phi [ x ] ) , 1ll * phi [ x ] ) ;
    return  tmp + 1ll * phi [ x ] ;
}

int  main ( ) {
    phi [ 1 ] = 0 ;
    vis [ 1 ] = true ;
    for ( int  i = 2 ; i <= 1e7 + 5 ; i ++ ) {
        if ( ! vis [ i ] ) {
            phi [ i ] = i - 1 ;
            prime [ ++ prime [ 0 ] ] = i ; 
        }
        for ( int  j = 1 ; j <= prime [ 0 ]  &&  prime [ j ] * i <= 1e7 + 5 ; j ++ ) {
            vis [ prime [ j ] * i ] = true ;
            if ( i % prime [ j ] == 0 ) {
                phi [ i * prime [ j ] ] = phi [ i ] * prime [ j ] ;
                break ;
            }
            else
                phi [ i * prime [ j ] ] = phi [ i ] * ( prime [ j ] - 1 ) ;
        }
    }
    scanf ( "%d" , & T ) ;
    for ( int  i = 1 ; i <= T ; i ++ ) {
        scanf ( "%lld" , & p ) ;
        printf ( "%lld\n" , pow ( 2 , dfs ( p ) , p ) ) ;
    }
    return  0 ;
}

其实不知道为什么,我在 BZOJ 和 洛谷 都 AC 了,但是有些同学 BZOJ 会 MLE,Emmm??

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值