[BZOJ4002]JLOI2015有意义的字符串|矩阵乘法

来源:互联网 发布:java日志等级 编辑:程序博客网 时间:2024/06/03 13:03

  题目和字符串有啥关系吗。。。
  熟悉特征方程就容易发现这其实是一个a[n]=c1a[n1]+c2a[n2]这样的数列的通项的一部分,a[n]=(b+d2)n+(bd2)n,其中c1=b,c2=db24,这样我们可以通过矩乘算出a[n]来。根据题目数据特点发现a[n]的后面项在(0.5,0.5)之内,那么只有n为偶数且d=b2时答案才是a[n]1,否则是a[n]。。注意各种爆范围。。。

#include<cstdio>#include<iostream>#include<memory.h>#include<cmath>#define p 7528443412579576937ul#define ll unsigned long longusing namespace std;struct ju{    ll a[2][2];    int n,m;}ans,t;ll b,d,n;ll mul(ll a,ll b){    if (b>a) swap(a,b);    if (b==0) return 0ll;    ll c=mul(a,b/2);    c=c*2%p;    if (b%2==1) c=(c+a)%p;    return c;}ju operator*(ju a,ju b){    ju ans;    memset(ans.a,0,sizeof(ans.a));    ans.n=a.n;ans.m=b.m;    for (int i=0;i<a.n;i++)        for (int j=0;j<a.m;j++)            for (int k=0;k<b.m;k++)                ans.a[i][k]=(ans.a[i][k]+mul(a.a[i][j],b.a[j][k]))%p;    return ans;}ju pow(ju a,ll b){    if (b==1) return a;    ju c=pow(a,b/2);    c=c*c;    if (b%2==1) c=c*a;    return c;}int main(){    cin>>b>>d>>n;    if (n==1) {cout<<b;return 0;}    if (n==0) {cout<<1;return 0;}    t.a[0][0]=0ll;t.a[0][1]=1ll;t.a[1][0]=((d-b*b)/4)%p;t.a[1][1]=b%p;    t.n=t.m=ans.n=2;ans.m=1;    ans.a[0][0]=2;ans.a[1][0]=b%p;    ans=pow(t,n-1)*ans;    if (d!=b*b&&n%2==0) ans.a[1][0]=(ans.a[1][0]-1+p)%p;    cout<<ans.a[1][0];}
0 0