首页 > 学院 > 开发设计 > 正文

[题解]bzoj4002(JLOI2015)有意义的字符串

2019-11-06 08:22:42
字体:
来源:转载
供稿:网友

Description

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

Input

一行三个整数 b;d;n

Output

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

Sample Input

1 5 9

Sample Output

76

HINT

其中 0<b2<=d<(b+1)2<=1018,n<=1018,并且 b mod 2=1,d mod 4=1

Solution

看看题目中的式子,想想初中数学,是不是很熟悉啊? 没错,他很像是一元二次方程的根。再联想一下n次方,于是神奇的发现他又像是某数列通项公式中的那个东东。 式子中可以看出,如果一元二次方程x2=px+q的一个根为 (b+d√2)n,那么Δ=p2+4q=dp=−b,所以根据通项公式可以构造出序列: an=b∗an−1+(d−b2)4∗an−2 他的通项公式为 an=A(b+d‾‾√2)n+B(b−d‾‾√2)n 为了方便计算,我们取A=B=1,所以 a0=2a1=b 而序列a的递推式中(d−b2)4,由于b mod 2=1,d mod 4=1,所以(d−b2)4一定是整数,所以矩阵乘法直接求出第n项,所以我们要的答案就是 (b+d‾‾√2)n=an−(b−d‾‾√2)n 由于题目中给出 b2<=d<(b+1)2,所以b−d√2∈(−1,0],当且仅当b2≠d且n为偶数时对答案有-1的贡献,所以答案要视情况减一。

注意模数太大,所以要开unsigned long long,并且要用快速乘取模。

代码:

#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>using namespace std;typedef unsigned long long LL;const LL mod=7528443412579576937;struct matrix{ LL a[2][2]; matrix(){memset(a,0,sizeof a);}}temp,I,c;LL b,d,n,ans;LL ksc(LL x,LL y){ LL re=0; while(y){ if(y&1)(re+=x)%=mod; (x+=x)%=mod;y>>=1; } return re;}matrix cheng(matrix x,matrix y){ matrix re; for(int i=0;i<2;i++){ for(int j=0;j<2;j++){ for(int k=0;k<2;k++){ (re.a[i][j]+=ksc(x.a[i][k],y.a[k][j]))%=mod; } } } return re;}matrix pow(matrix x,LL y){ matrix re=I; while(y){ if(y&1)re=cheng(re,x); x=cheng(x,x);y>>=1; } return re;}int main(){ cin>>b>>d>>n; I.a[0][0]=I.a[1][1]=1; temp.a[0][0]=b;temp.a[0][1]=2; c.a[0][0]=b;c.a[0][1]=1;c.a[1][0]=(d-b*b)/4; if(n==0)return PRintf("1/n"),0; temp=cheng(temp,pow(c,n-1)); ans=temp.a[0][0]; if(!(n&1)&&b*b!=d)ans--; cout<<(ans+mod)%mod<<endl; return 0;}
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表