快速模幂,大数模小数
https://ac.nowcoder.com/acm/contest/330/E
链接:https://ac.nowcoder.com/acm/contest/330/E
来源:牛客网
精通程序设计的 Applese 叕写了一个游戏。
在这个游戏中,有一个 n 行 m 列的方阵。现在它要为这个方阵涂上黑白两种颜色。规定左右相邻两格的颜色不能相同。请你帮它统计一下有多少种涂色的方法。由于答案很大,你需要将答案对 109+7109+7 取模。
输入描述:
仅一行两个正整数 n, m,表示方阵的大小。
输出描述:
输出一个正整数,表示方案数对 10^9+7 取模。
示例1
输入
1 1
输出
2
示例2
输入
2 2
输出
4
由题意知所求的只是2^n mod 1000000007即可
根据数论知识有A^B mod P = A ^ ( euler(P) + B mod euler(P) ) mod P 即可
由此可以避免掉使用高精度的麻烦。
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
typedef long long ll;
const int mod=1000000007;
int c;
char str[100005];
void quick_mod(ll n){
ll a=2,k=1;
while(n){
if(n%2==1){
k=k*a;
k%=mod;
}
a=a*a%mod;
n/=2;
}
cout<<(k*2)%mod<<endl;
}
void euler(int n){ //返回euler(n)
int res=n,a=n;
for(int i=2;i*i<=a;i++){
if(a%i==0){
res=res/i*(i-1);
while(a%i==0) a/=i;
}
}
if(a>1) res=res/a*(a-1);
c=res;
}
char sss[100005];
int main()
{
euler(mod);
ll b=0;
scanf("%s%s",str,sss);
int len=strlen(str);
for(int i=len-1;i>=0;i--){
if(str[i]=='0'){
str[i]='9';
}
else{
str[i]=(char)((int)(str[i])-1);
break;
}
}
for(int i=0;i<len;i++){
b=b*10+str[i]-'0';
if(b>c)
b=b%c;
}
quick_mod(b+c);
return 0;
}
或:
#include<bits/stdc++.h>
using namespace std;
char x1[200005];char x2[200005];
typedef long long ll;
ll pow(ll x,ll n,ll mod)
{
ll res=1;
while(n>0)
{
if(n%2==1)
{
res=res*x;
res=res%mod;
}
x=x*x;
x=x%mod;
n>>=1;
}
return res;
}
ll n,m;
const ll P=1000000007;
ll f(char s[])
{
int len=strlen(s);
ll tmp=1;
ll res=0;
for(int i=len-1;i>=0;i--)
{
res=(res+((s[i]-'0')*tmp%(P-1)))%(P-1);
tmp=(tmp*10)%(P-1);
}
return res;
}
int main()
{
scanf("%s%s",x1,x2);
n=f(x1);
ll ans=pow(2,n+1000000006,P);
cout<<ans<<endl;
return 0;
}