2017 Multi-University Training Contest - Team 2 :1006 Funny Function(找规律+逆元+快速幂取模)
2017-07-31 19:18
633 查看
Funny Function
[b]Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1192 Accepted Submission(s): 580
[/b]
[align=left]Problem Description[/align]
Function Fx,ysatisfies:
For given integers N and M,calculate Fm,1
modulo 1e9+7.
[align=left]Input[/align]
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.
[align=left]Output[/align]
For each given N and M,print the answer in a single line.
[align=left]Sample Input[/align]
2
2 2
3 3
[align=left]Sample Output[/align]
2
33
题目给出了三个公式。
第一行F[1][1] = F[1][2] = 1;
第一行的其他数F[i][j] = F[i][j-1] + 2*F[i][j-2]。 当j》=3的时候,
当i>=2的时候,F[i][j] 等于i-1行从j开始n个数的和。
给出n,m,求F【m,1】的值。
比赛时画了四张纸,还是没有找出规律,只是发现了n,m的奇、偶性对答案的影响时不同的。看官方题解和
其他人写的式子,我真的退不出来最后的公式,不过在网上发现了一篇文章,就是单纯的去讲他们当时比赛怎么
找规律找出来的,我还勉强可以理解理解。原文作者链接:https://www.dreamwings.cn/hdu6050/4839.html
首先找这种二维数组的规律,我们可以借助Excel表,有格子,比较好看。下面是我用Excel表制的数据
当时我们也写了挺多,就是在纸上写的太乱了,算了后面的数,前面的就丢了,不直观。还是Excel弄出来比较整齐。
或者可以编程计算将数据都写入文件。
然后开始找规律:
当n=2的时候,从第三行开始,发现6/2 = 3 18/6 = 3 54/18 = 3. 我们发现当n=2的时候,F[m][1]/F[m-1][1] = 3 (m>=3)
当n=4的时候,从第三行开始,发现150/10 = 15 2250/150=15.。。。我们发现当n=4的时候,F[m][1]/F[m-1][1] = 15 (m>=3)
这样来看比值3 和 n值2有什么关系, 比值15 和n值4有什么关系, 比较容易发现比值等于2^n-1.
那么规律都是这样的吗。
再来看n为奇数的情况。
然后我们来看当 nn
为奇数的情况,还照之前的做法我们把相邻的两项相除,可以发现这个值无限趋近于
2n−1,于是想到会不会相差某一个数字呢。
然后计算
Fm−1,1×(2n−1)−Fm,1,
F[m-1][1]*(2^n-1)-F[m][1] ,发现果真相差一个常数,接下来的工作便是寻找这个常数与什么有关了。
当 n=3..5..7..9n=3..5..7..9
时,该常数为: 2..10..42..1702..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
................这个规律真的不太好找。
也就是公比为4,的等比数列的前k项和,公式Sk = a1*(1-q^k)/(1-q),其中首项a1 = 2,公比q = 4,项数k=n/2.将这些值带入上式就能得到,前k
项和。
我们设cha为我们所求得得差,假如F[2][1]时已知得,2^n-1也已知,然后我们如何通过这三者得到F[m][1]呢?
F[3][1] = F[2][1]*(2^n-1) - cha
F[4][1] = F[3][1]*(2^n-1) - cha = F[2][1]*(2^n-1)^2 - cha*(2^n-1) - cha
F[5][1] = F[4][1]*(2^n-1) - cha = F[2][1]*(2^n-1)^3 - cha*(2^n-1)^2 - cha*(2^n-1) - cha
....................
F[m][1] = F[m-1][1]*(2^n-1) - cha = F[2][1]*(2^n-1)^(m-2) - cha*(2^n-1)^(m-3)-.......- cha*(2^n-1)-cha
可以看出后面的 cha*(2^n-1)^(m-3) + cha*(2^n-1)^(m-4) + cha*(2^n-1)^(m-5) + ... + cha*(2^n-1) + cha
把cha提出来后,又是一个等比数列求和,首相为1,公比为(2^n-1),项数为m-2。
则现在是只有F[2][1]不知道了,而F[2][1]又等于第一行前n项的和,那它怎么得到呢,每次给出一个n值,算出第一行
前n个数再求和吗?结果发现F[2][1]也又规律。下面的S[i]为第一行的前i项和,
同样也有规律的,先打表看看~
S[i]: 1 2 5 10 21 42 85 170 341 682 1365 2730 5461 10922 21845 43690 87381 174762 349525 F[i]: 1 1 3 5 11 21 43 85 171 341 683 1365 2731 5461 10923 21845 43691 87381 174763 349525
如果把s[i]整体往后推一位,
S[i]: 1 2 5 10 21 42 85 170 341 682 1365 2730 5461 10922 21845 43690 87381 174762 349525
F[i]: 1 1 3 5 11 21 43 85 171 341 683 1365 2731 5461 10923 21845 43691 87381 174763 349525
当n为奇数的时候,S
= F[2][1] = F[1][n+1]
当n为偶数的时候,S
= F[2][1] = F[1][n+1] - 1;
所以当给出一个n的时候,只要能算出F[1][n+1],就可以计算出F[2][1]的值。
看别人的博客推出F[1][n+1]也有一个公式F[1][n+1] = ( (-1)^i + 2^(i+1))/3,但是我都看不懂这个式子。
但是之前我用矩阵快速幂求过斐波那契数列,所以我就用矩阵快速幂推导第一行的第n+1项。
首先再第一行我们知道,对于n>=3 Fn = Fn-1 + 2*Fn-2.
则对于n>=3我们可以写出下列矩阵来推导
现在总结公式:
除法过程中取模要用到逆元,因为要取模的那个数时素数,所以可以用小费马定理去求逆元。
AC代码:
#include <iostream> #include <stdio.h> using namespace std; const int mod = 1e9+7; typedef long long LL; /*F[1][i] = F[1][i-1] + 2*F[1][i-2],(i>=3)时成立, 又因为F[2][1]等于第一行前n项和相加,当n%2==0.sn = F[1][n+1]-1 当n%2==1,sn = F[1][n+1].所以可以通过矩阵快速幂求F[1][n+1].*/ struct Matrix { LL a[4][4]; }; ///进行矩阵乘法的函数 Matrix Matrix_Mul(Matrix b,Matrix c) { Matrix tmp; for(int i = 1; i <= 2; i++) for(int j = 1; j <= 2; j++) tmp.a[i][j] = 0; for(int i = 1; i <= 2; i++) for(int j = 1; j <= 2; j++) for(int k = 1; k <= 2; k++) tmp.a[i][j] = ((b.a[i][k]*c.a[k][j])%mod+tmp.a[i][j])%mod; return tmp; } ///矩阵快速幂计算F[1][n+1] LL Matrix_Quick_Pow(LL k) { if(k==1 || k==2) return 1; Matrix ans,res; res.a[1][1] = 1; res.a[1][2] = 2; res.a[2][1] = 1; res.a[2][2] = 0; ans.a[1][1] = 1; ans.a[1][2] = 0; ans.a[2][1] = 0; ans.a[2][2] = 1; k = k-2; while(k) { if(k&1) ans = Matrix_Mul(ans,res); res = Matrix_Mul(res,res); k = k>>1; } return (ans.a[1][1]+ans.a[1][2])%mod; } ///整数快速幂函数,求t的k次方 LL Integer_Quick_Pow(LL t,LL k) { LL ans,res; ans = 1; res = t; while(k) { if(k&1) ans = (ans*res)%mod; res = (res*res)%mod; k = k>>1; } return ans; } int main() { LL n,m,ans; int t; cin>>t; while(t--) { cin>>n>>m; if(m == 1) cout<<"1"<<endl; else { ///矩阵快速幂计算F[1][n+1]。 LL Sn = Matrix_Quick_Pow(n+1); if(n%2==0) Sn = (Sn-1+mod)%mod; ///计算出F[2][1] LL tmp1=Integer_Quick_Pow(2,n); ///计算2^n tmp1 = (tmp1-1+mod)%mod; ///计算2^n-1 LL tmp2 = Integer_Quick_Pow(tmp1,m-2); ///计算(2^n-1)^(m-2) if(n%2==0) { ans = (Sn*tmp2)%mod; } else { LL term = n/2; ///项数 LL tmp3 = Integer_Quick_Pow(4,term); ///4^term tmp3 = (tmp3-1+mod)%mod; ///4^term-1 LL x = Integer_Quick_Pow(3,mod-2); ///求3的逆元 tmp3 = ((2*tmp3)%mod)*x%mod; LL y = Integer_Quick_Pow((tmp1-1+mod)%mod,mod-2); LL tmp4 = (tmp2-1+mod)%mod; tmp4 = (tmp3*tmp4)%mod*y%mod; ans = ((Sn*tmp2)%mod-tmp4+mod)%mod; } cout<<ans<<endl; } } return 0; }
相关文章推荐
- 2017 Multi-University Training Contest - Team 1 1006&&HDU 6038 Function【DFS+数论】
- 2017 Multi-University Training Contest - Team 1 1006 Function(置换群)
- 2017 Multi-University Training Contest - Team 1 1006 Function
- 2017 Multi-University Training Contest - Team 1--1006 Function
- 2017 Multi-University Training Contest - Team 1 1006 Function
- HDU 6038 Function(找规律)——2017 Multi-University Training Contest - Team 1
- 2017 Multi-University Training Contest 2 && HDOJ 6050 Funny Function 【思维+快速幂】
- hdoj 6050(2017 Multi-University Training Contest - Team 2) Funny Function
- 2017 Multi-University Training Contest - Team 1 1006 Function(思维 循环节)
- HDU 6050 Funny Function(构造矩阵+推公式)——2017 Multi-University Training Contest - Team 2
- HDU-6105 Gameia - 2017 Multi-University Training Contest - Team 6(思维之找规律或二分图最大匹配)
- 2017 Multi-University Training Contest - Team 1 1011&&HDU 6043 KazaQ's Socks【规律题,数学,水】
- 2017 Multi-University Training Contest 10 1002 Array Challenge HDU 6172(找规律 矩阵快速幂)
- 2017 Multi-University Training Contest - Team 1 :Function
- hdu 6038 找规律 置换 2017 Multi-University Training Contest - Team 1
- 2017 Multi-University Training Contest - Team 1(hdu 6038 Function)
- 2017 Multi-University Training Contest - Team 2 hdu6050 Funny Function 矩阵快速幂
- 2017 Multi-University Training Contest - Team 5 1006 Rikka with Graph
- HDU 6048 Puzzle(找规律)——2017 Multi-University Training Contest - Team 2
- 2017 Multi-University Training Contest - Team 1 Function