zoukankan      html  css  js  c++  java
  • [BZOJ4002][JLOI2015]有意义的字符串-[快速乘法+矩阵乘法]

    Description

    传送门

    Solution

    由于这里带了小数,直接计算显然会爆掉,我们要想办法去掉小数。

    而由于原题给了暗示:b2<=d<=(b+1)2我们猜测可以利用$(frac{b-sqrt{d}}{2})^{n}$的范围为(-1,1)的性质。

    则$ans=((frac{b+sqrt{d}}{2})^{n}+(frac{b-sqrt{d}}{2})^{n})-(frac{b-sqrt{d}}{2})^{n}$。

    易得第一个括号里的式子不包含小数(强行组合数算一下就发现啦)

    我们考虑特征方程,

    现在定义$a_{n}=(frac{b+sqrt{d}}{2})^{n}+(frac{b-sqrt{d}}{2})^{n}$

    解得$a_{n}=b*a_{n-1}+frac{(d-b^{2})}{4}*a_{n-2}$

    其中,边界a0=2,a1=b。

    然后矩阵乘法就好啦。(备注:由于此处两个数相乘会过大,需要用到快速乘法,log(n)的那种)

    最后,如果 $(frac{b-sqrt{d}}{2})^{n}geqslant 0$,则由于题目向下取整,可以忽略;

    故只有$b^{2} eq d$且n为奇数才需要对答案减一。

    Code

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    using namespace std;
    typedef unsigned long long ull;
    const ull mod=7528443412579576937ull;
    ull b,d,n;
    ull mul(ull a,ull b)
    {
        ull ans=0;
        while(b)
        {
            if(b&1) ans=(a+ans)%mod;
            b>>=1;a=(a+a)%mod; 
        }
        return ans;
    }
    struct Matrix{ull x[3][3];
        friend Matrix operator*(Matrix a,Matrix b)
        {
            Matrix c;memset(c.x,0,sizeof(c.x));
            for (int i=1;i<=2;i++)
                for (int j=1;j<=2;j++)
                    for (int k=1;k<=2;k++)
                        c.x[i][j]=(c.x[i][j]+mul(a.x[i][k],b.x[k][j]))%mod;
            return c;
        }
    }a;
    Matrix ksm(Matrix a,ull t)
    {
        Matrix ans;memset(ans.x,0,sizeof(ans.x));
        ans.x[1][1]=ans.x[2][2]=1;
        while (t)
        {
            if (t&1) ans=ans*a;
            t>>=1;
            a=a*a;
        }
        return ans;
    }
    ull ans;
    int main()
    {
        scanf("%llu%llu%llu",&b,&d,&n);
        if (!n) {printf("1");return 0;}
        a.x[1][1]=b;
        a.x[1][2]=(d-b*b)/4%mod;
        a.x[2][1]=1;
        a.x[2][2]=0;
        a=ksm(a,n-1);
        ans=(mul(b,a.x[1][1])+mul(2,a.x[1][2]))%mod;
        if (d!=b*b&&!(n&1)) ans--;
        if (ans<0) ans+=mod;
        cout<<ans;
    } 
  • 相关阅读:
    C#使用SSDB管理增量日志并提供查询
    请假系统特例规则详细设计
    2014年国内最热门的.NET开源平台
    MQTT--入门
    转MQTT--Python进行发布、订阅测试
    Python修改文件权限
    Python Windows文件操作
    python random 学习
    Python---copy()、deepcopy()与赋值的区别
    使用Git Bash从Git上下载代码到本地以及上传代码到码云Git
  • 原文地址:https://www.cnblogs.com/coco-night/p/9545024.html
Copyright © 2011-2022 走看看