題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=6050
Funny Function
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1346 Accepted Submission(s): 686
Problem Description
Function Fx,ysatisfies:
For given integers N and M,calculate Fm,1 modulo 1e9+7.
Input
There is one integer T in the first line.
The next T lines,each line includes two integers N and M .
1<=T<=10000,1<=N,M<2^63.
Output
For each given N and M,print the answer in a single line.
Sample Input
2
2 2
3 3
Sample Output
2
33
Source
2017 Multi-University Training Contest - Team 2
首先推薦一篇比較好的博客:戳這裏
這道題的數據量很大,如果一個個算的話數據量是很大的
我們可以試着找找規律:
n=2:1 2 6 18
n=3:1 5 33 229
n=4:1 10 150 2250
n=5:1 21 641 19861
從中可以看出:
當n是偶數時,從第二項開始後一項與前一項的比值都是固定的,且是2^n-1
當n是奇數時,從第二項開始後一項都是前一項固定倍數再減去一個固定值,這個固定值也是有規律可循的。
即(規律):
當n爲偶數時,f[m]=f[m-1](2^n-1) (m>=3)即f[m]=f[2](2^n-1)^(m-2);
當n爲奇數時,f[m]=f[m-1]*(2^n-1)-(2^1+…..+2^(n-2)) (m>=3);
當n=當 n=3..5..7..9 時,該常數爲: 2..10..42..170;
2=2^1 10=2^1+2^3 42=2^1+2^3 +2^5 170=2^1+2^3 +2^5 +2^7
當然,規律找到這也不是最簡的
最終規律:
不過從我能得到的規律到最終規律這幾步沒有推出來。
好多人都是用矩陣快速冪做的,我在開始推薦的博客裏面兩種方法都有。
注意:在對除數取餘的時候爲了防止精度的丟失,需要用到乘法的逆元,將除法變成乘法。這裏使用的乘法逆元算法爲費馬小定理。
**費馬小定理
在p是素數的情況下,對任意整數x都有x^p≡x(mod)p。
可以在p爲素數的情況下求出一個數的逆元,x∗x^(p−2)≡1(mod p),x^(p−2)即爲逆元。**
這個定理我也是第一次接觸
乘法逆元講解:http://blog.csdn.net/a27038/article/details/77017706
代碼:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int MAX=1e5+10;
const int mod=1e9+7;
typedef long long LL;
LL km(LL a,LL b)
{//快速冪求a^b%mod;
LL ans=1;
while(b)
{
if(b&1)
ans=(ans*a)%mod;
b>>=1;
a=(a*a)%mod;
}
return ans;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
LL n,m,ans;
scanf("%lld%lld",&n,&m);
LL k=(km(2,n)-1)%mod;
LL k1=(km(k,m-1)*2)%mod;
if(n%2!=0)
k1++;
ans=(k1 * km(3,mod - 2)) % mod;
printf("%lld\n",ans);
}
return 0;
}