题目大意:Pupu有N层皮,每一层要么是透明,要么是不透明的,每天被太阳晒到的就会变一次,设N层刚出生都不透明,要全部皮都至少变过一次要多少天?(答案MOD N)

解题思路:1)理解题目:
                 注意注意,题目所求的是每层皮肤至少变一次的天数,不是全部变成透明的天数!...
                 .坑爹的,它里面写的是(that all of a PuPu's skins has been changed from opacity to clarity )
              2)设f[n]为前n层皮肤变成透明所需要的天数,ans[n]为全部皮肤至少变一次的天数。
                   易得:f[n]=2*f[n-1];
                           ans[n]=f[n-1]+1;             ==>ans[n]=2^(n-1)+1;
                           f[1]=2   (0->1    两天);
              3)这里ans的增长率很客观,所以答案要进行取模,便涉及到一个大数取模((logb)^3)的运算。
                  1、首先将b化为二进制数:即b=(AtAt-1At-2.....A0)2=At*2^t+At-1*2^(t-1).....+A0;
                  2、a^b % c = a^(At*2^t+At-1*2^(t-1)+.....+A0)%c=((a^(At*2^t))%c*(a^(A(t-1)*2^(t-1)))%c*.......*(a^(A0)%c))
                        (*....这式子看起来好恶心......*)
                  3、对于每一个a^(2^(i+1))%c=(a^(2^i)%c)^2%c
                         这样我们就可以在常数时间内由2^n项推到2^(n+1)项了。
                  大数取模模版(吉林大学):
                

 1long long mod_exp(long long a,long long b0,long long n)
 2{
 3    if( a > n ) a %= n;
 4    long long i, d = 1, b[35];
 5    for( i=0; i < 35++i ){
 6        b[i] = b0%2;
 7        b0 /= 2;
 8        if( b0 == 0 )  break;
 9    }

10    for( ;i >= 0--i ){
11        d = (d*d)%n;
12        if( b[i] == 1 )  d = (d*a)%n;
13    }

14    return d;
15}




代码:

 1#include <iostream>
 2#include <cstdio>
 3#include <cstring>
 4#include <cmath>
 5
 6using namespace std;
 7
 8int n;
 9
10long long mod_exp(long long a,long long b0,long long n)
11{
12    if( a > n ) a %= n;
13    long long i, d = 1, b[35];
14    for( i=0; i < 35++i ){
15        b[i] = b0%2;
16        b0 /= 2;
17        if( b0 == 0 )  break;
18    }

19    for( ;i >= 0--i ){
20        d = (d*d)%n;
21        if( b[i] == 1 )  d = (d*a)%n;
22    }

23    return d;
24}

25
26int main()
27{
28    while(~scanf("%d",&n))
29    {
30        if(n == 0break;
31        printf("%I64d\n",(mod_exp(2,(n-1),n)+1)%n);
32    }

33    return 0;
34}

35