zoukankan      html  css  js  c++  java
  • bzoj4002: [JLOI2015]有意义的字符串

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

    Time Limit: 10 Sec  Memory Limit: 128 MB

    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

    Source

    Tip:

      高中有教过特征根方程;

      当An=p*A(n-1)+q*A(n-2)时

      x2=p*x+q的两个方程根x1,x2;

      An=Ax1n+Bx2n

      此题x1=(b+d0.5)/2,x2=(b-d0.5)/2;

      反解得p=b,q=(d-b*b)/4; 根据题意 q 算出来是一个整数。

      An=((b+d0.5)/2)n+((b-d0.5)/2)n

      ((b+d0.5)/2)n=An-((b-d0.5)/2)n

      -1 <= ((b-d0.5)/2)n <= 1

      当n为偶数且b!=d*d时-1,其余情况无影响;

      用矩阵乘法求An即可;

      注意unsigned long long,不过某些大佬好像没用,我也不清楚怎么做的%%%;

    Code:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    
    const unsigned long long MOD=7528443412579576937;
    unsigned long long b,d,n,a[3][3],bb[3][3],ans[3][3],f,res;
    
    unsigned long long mul(unsigned long long aa,unsigned long long bb){
        unsigned long long g=0; aa%=MOD;
        for(unsigned long long i=bb;i;i>>=1,aa=aa*2%MOD)
            if(i%2==1) g=(g+aa)%MOD;
        return g;
    }
    
    void ch(){
        for(int i=1;i<=2;i++)
            for(int j=1;j<=2;j++){
                bb[i][j]=0;
                for(int k=1;k<=2;k++)
                    bb[i][j]=(bb[i][j]+mul(a[i][k],ans[k][j])%MOD)%MOD;
            }
        for(int i=1;i<=2;i++)
            for(int j=1;j<=2;j++)
                ans[i][j]=bb[i][j];
    }
    
    void cc(){
        for(int i=1;i<=2;i++)
            for(int j=1;j<=2;j++){
                bb[i][j]=0;
                for(int k=1;k<=2;k++)
                    bb[i][j]=(bb[i][j]+mul(a[i][k],a[k][j])%MOD)%MOD;
            }
        for(int i=1;i<=2;i++)
            for(int j=1;j<=2;j++)
                a[i][j]=bb[i][j];
    }
    
    int main(){
        scanf("%lld%lld%lld",&b,&d,&n);
        a[1][2]=1;
        a[2][1]=(d-b*b)/4;
        a[2][2]=b;
        if(n%2==0 && b*b!=d) f=-1;
        if(n==0){
            printf("1");
            return 0;
        }
        ans[1][1]=ans[2][2]=1;
        while(n>0){
            if(n%2==1) ch();
            cc();
            n=n/2;
        }
        res=(2*ans[1][1]%MOD+mul(ans[1][2],b))%MOD;
        printf("%lld",(res+f+MOD)%MOD);
    }
  • 相关阅读:
    JAVA实现文件遍历
    关于java的JIT知识
    经典的01背包问题
    文件遍历
    [算法之动态规划] 基本思想
    软件设计经典书籍推荐
    C++ 学习之函数重载、基于const的重载
    tomcat调用axis服务时出现 java.lang.InvocationException解决方案
    文件上传的原理
    文件上传的原理
  • 原文地址:https://www.cnblogs.com/WQHui/p/8419409.html
Copyright © 2011-2022 走看看