bzoj 4002: [JLOI2015]有意义的字符串(特征根法+矩阵快速幂)

来源:互联网 发布:信用卡账单修改软件 编辑:程序博客网 时间:2024/06/04 17:51

4002: [JLOI2015]有意义的字符串

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 960  Solved: 415
[Submit][Status][Discuss]

Description

 B 君有两个好朋友,他们叫宁宁和冉冉。有一天,冉冉遇到了一个有趣的题目:输入 b;d;n,求

Input

一行三个整数 b;d;n

Output

 一行一个数表示模 7528443412579576937 之后的结果。

Sample Input

1 5 9

Sample Output

76

HINT

其中 0<b^2< = d<(b+1)2< = 10^18,n< = 10^18,并且 b mod 2=1,d mod 4=1


还记不记得斐波那契数列的通项公式


考虑先求


这其实是一个三项递推数列的通项公式,而数列的递推式如下

可以用特征根法求出这个方程)

有了递推式,矩阵快速幂就搞定了

因为b%2=1, d%4=1,所以b²-d一定是4的倍数

又因为b²<=d<(b+1)²,所以有


因为是向下取整,所以当b²!=d && n%2==0时答案-1

要用unsigned long long


#include<stdio.h>#include<string.h>#define mod 7528443412579576937ll#define LL unsigned long longtypedef struct{int i, j;LL a[4][4];void init(){memset(a, 0, sizeof(a));}void unit(){memset(a, 0, sizeof(a));for(i=1;i<=2;i++)a[i][i] = 1;}}Matrix;Matrix Powto(Matrix p, LL k);Matrix Jjcf(Matrix p1, Matrix p2);LL Mul(LL x, LL y){LL ans = 0;if(x>y)x = x+y, y = x-y, x = x-y;x %= mod;while(y){if(y%2)ans = (ans+x)%mod;x = (x+x)%mod;y /= 2;}return ans;}int main(void){Matrix Jz;LL b, d, n, ans;scanf("%llu%llu%llu", &b, &d, &n);Jz.init();Jz.a[1][1] = b, Jz.a[1][2] = (d-b*b)/4;Jz.a[2][1] = 1;if(n==0)ans = 2;else if(n==1)ans = b;else{Jz = Powto(Jz, n-1);ans = (Mul(Jz.a[1][1], b)+Jz.a[1][2]*2)%mod;}if(b*b!=d && n%2==0)ans = (ans-1+mod)%mod;printf("%llu\n", ans);return 0;}Matrix Powto(Matrix p, LL k){Matrix E;E.unit();while(k){if(k%2)E = Jjcf(E, p);p = Jjcf(p, p);k /= 2;}return E;}Matrix Jjcf(Matrix p1, Matrix p2){Matrix pe;int i, j, k;pe.init();for(i=1;i<=2;i++){for(j=1;j<=2;j++){for(k=1;k<=2;k++)pe.a[i][j] = (pe.a[i][j]+Mul(p1.a[i][k], p2.a[k][j]))%mod;}}return pe;}


阅读全文
1 0
原创粉丝点击