链接:https://ac.nowcoder.com/acm/contest/330/E
来源:牛客网
 

在这个游戏中,有一个 n 行 m 列的方阵。现在它要为这个方阵涂上黑白两种颜色。规定左右相邻两格的颜色不能相同。请你帮它统计一下有多少种涂色的方法。由于答案很大,你需要将答案对 109+7109+7 取模。

输入描述:

仅一行两个正整数 n, m,表示方阵的大小。

输出描述:

输出一个正整数,表示方案数对 109+7109+7 取模。

示例1

输入

复制

1 1

输出

复制

2

示例2

输入

复制

2 2

输出

复制

4

备注:

1≤n,m≤

 

其实这个题看懂了很简单,只要你确定了第一列,那么剩下的就确定了,那么第一列怎么确定呢,一个格子可以选择两种颜色,

那么一列n个格子,就有种情况

那么新的问题来了,题上可知N最大为10的1000000次,而longlong最多也就10的18次,那怎么求这超级无敌雷霆霹雳大的次幂呢?

费马小定理登场!

定理内容:假如p是质数,且gcd(a,p)=1(也就是a不为p的倍数),那么 a^(p-1)≡1(mod p)

由题可知,1e9+7是个质数,2是整数,a与p互质显而易见,所以现在我们的目的就是想办法把(%(1e9+7)降幂为2^k%(1e9+7)

已知a^(p-1) = 1,且n可能很大很大,就看n里包括多少个p-1,把这些都丢掉求剩下的就好。假设有x个p-1(p=1e9+7)则: = * ,所以直接求2^k就好,k = (n)%(p-1)

由于n过于长,就用字符串存储,之后边转化为数边取余,最后结果quick_pow(2,ans)%mod即可。 

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod=1e9+7; 
ll pow1(ll a,ll b)
{
    ll r=1;
    while(b)
    {
        if(b&1) r=r*a%mod;
        a=a*a%mod;
        b/=2;
    }
    return r;
}
int main()
{
   string a,b;
   cin>>a>>b;
   ll ans=0;
   int len=a.size();
   for(int i=0;i<len;i++)
    ans=(ans*10+a[i]-'0')%(mod-1);
   printf("%lld\n",pow1(2ll,ans));
}