链接: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));
}