JLOI2015 有意义的字符串

Description
 
Input
一行三个整数b, d, n。
Output
一行一个数表示模7528443412579576937 之后的结果。
 
Sample Input
输入1:
1 5 9
输入2:
11 125 6715504
Sample Output
输出1:
76
输出2:
1499928102740042526
 
Data Constraint
 

好吧。一直没看懂题目名到底有意义在哪= =

进入正题

 

首先我们发现(b+sqrt(d))/2可以是某个方程的解,它符合(-b+sqrt(b*b-4ac))/2a的形式。

我们发现这个方程是x^2=bx+(d-b^2)/4;

我们假设一个数列f[n]=((b+sqrt(d))/2)^n;

由刚才的方程可得f[n]满足f[n]=bf[n-1]+(d-b^2)/4*f[n-2]

所以对于((b+sqrt(d))/2的n次方我们可以矩乘快速幂求得。

但实数直接上mod是会挂的!

我们接着发现方程另外一根为((b-sqrt(d))/2;

那么它同样满足上面的递推式

我们设h[n]=((b+sqrt(d))/2)^n+((b+sqrt(d))/2)^n,那么h[n]同样满足递推式,而且h[n]是整数!!!

又因为((b+sqrt(d)/2)^n绝对值小于1,所以它的影响我们可以直接特判,

就这样,

另外,由于mod的数太大,乘法我们要用快速乘实现

 

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<cstring>

using namespace std;
typedef long long ll;

struct Matrix{
    ll a[4][4];
    int n,m;
}dw,dl,y;

ll mo=7528443412579576937ll;
ll ans,n,b,d;

ll add(ll a,ll b)
{
    ll lef;
    lef=mo-a;
    if(b<=lef)a=a+b;
    else a=b-lef;
    return a;
}

ll mul(ll a,ll b)
{
    ll l;
    l=0;
    while(b){
        if(b%2==1)l=add(l,a);
        a=add(a,a);
        b/=2;
    }
    return l;
}

Matrix operator *(Matrix a,Matrix b)
{
    Matrix c;
    int i,j,k;
    memset(c.a,0,sizeof(c.a));
    c.n=a.n;c.m=b.m;
    for(i=1;i<=a.n;i++)
        for(j=1;j<=b.m;j++){
            c.a[i][j]=0;
            for(k=1;k<=a.m;k++)c.a[i][j]=add(c.a[i][j],mul(a.a[i][k],b.a[k][j]));
        }
    return c;
}

Matrix mi(Matrix x,ll z)
{
    Matrix l;
    l.n=l.m=2;
    memset(l.a,0,sizeof(l.a));
    l.a[1][1]=1;l.a[2][2]=1;
    while(z){
        if(z%2==1)l=l*x;
        x=x*x;
        z/=2;
    }
    return l;
}


int main()
{
    scanf("%lld%lld%lld",&b,&d,&n);
    dw.a[1][1]=0;dw.a[1][2]=(d-b*b)/4;
    dw.a[2][1]=1;dw.a[2][2]=b;
    dw.n=dw.m=2;
    dl=mi(dw,n);
    if(n==0)ans=1;
    else{
        ans=mul(dl.a[1][1],2);
        ans=add(ans,mul(b,dl.a[2][1]));
        if(d!=b*b&&n%2==0)ans--;
        if(ans<0)ans+=mo;
    }
    printf("%lld\n",ans);
}

 

转载于:https://www.cnblogs.com/applejxt/p/4480501.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值