zoukankan      html  css  js  c++  java
  • 【BZOJ4002】[JLOI2015]有意义的字符串

    题意:

    给出b,d,n,求$lfloor(frac{b+sqrt{d}}{2})^n floor mod 999999999999999989$(原题是7528443412579576937)。

    $nleq 10^{18}$

    $0<b^2leq d<(b+1)^2leq 10^{18}$

    $b mod 2=1$

    $d mod 4=1$

    对于20%的数据有$b=1,d=5$

    题解:

    我是不知道这题跟字符串有什么关系。。。

    场上有40%的数据是$nleq 5$然而我们都没搞出来。。。
    本质是发现性质然后乱搞。。。(这场数学竞赛的本质)

    观察式子$(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-(frac{b-sqrt{d}}{2})^n$;

    然后我们可以通过一些黑科技用通项把递推式还原出来:把两个共轭根式看成特征方程的两个解,再通过韦达定理就可以把原来的系数解出来。。。

    有兴趣的同学可以自己算一下,这里算出来特征方程是$x^2-bx+frac{b^2-d}{4}=0$,那么还原出来递推式就是

    $a_n=b imes a_{n-1}+frac{d-b^2}{4} imes a_{n-2}$,其中$a_0=2,a_1=b$

    所以可以用矩阵快速乘来搞定数列,再考虑后面的$(frac{b-sqrt{d}}{2})^n$;

    由于数据有$b^2leq d<(b+1)^2$或$b=1,d=5$,所以$(frac{b-sqrt{d}}{2})^n∈(-1,0]$,当且仅当$d≠b^2$且$n$为偶数时要把答案减一。

    时间复杂度$O(log^2n)$,但是原题模数爆longlong,所以要手写快速乘。。。

    代码:

     1 #include<algorithm>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<cmath>
     6 #define eps 1e-4
     7 #define mod 999999999999999989ll
     8 using namespace std;
     9 typedef unsigned long long ull;
    10 struct sq{
    11     ull a[2][2];
    12     sq(){
    13         a[0][0]=a[0][1]=a[1][0]=a[1][1]=0;
    14     }
    15     void init(){
    16         a[0][0]=a[1][1]=1;
    17     }
    18 }a,ans;
    19 ull calc(ull x,ull y){
    20     ull ret=0;
    21     for(;y;y>>=1,x=(x+x>mod)?x+x-mod:x+x){
    22         if(y&1)ret=(ret+x>mod)?ret+x-mod:ret+x;
    23     }
    24     return ret;
    25 }
    26 sq operator *(const sq a,const sq b){
    27     sq ret;
    28     for(int i=0;i<2;i++)for(int j=0;j<2;j++)for(int k=0;k<2;k++){
    29         ret.a[i][j]=(ret.a[i][j]+calc(a.a[i][k],b.a[k][j]))%mod;
    30     }
    31     return ret;
    32 }
    33 sq pw(sq x,ull y){
    34     sq ret;
    35     ret.init();
    36     for(;y;y>>=1,x=x*x){
    37         if(y&1)ret=ret*x;
    38     }
    39     return ret;
    40 }
    41 ull b,d,n;
    42 int main(){
    43     scanf("%llu %llu %llu",&b,&d,&n);
    44     a.a[1][0]=1;
    45     a.a[0][1]=(d-b*b)/4;
    46     a.a[1][1]=b;
    47     ans.a[0][0]=2;
    48     ans.a[0][1]=b;
    49     ans=ans*pw(a,n);
    50     if(n%2==0&&d!=b*b)ans.a[0][0]--;
    51     printf("%llu",ans.a[0][0]);
    52     return 0;
    53 }
  • 相关阅读:
    为什么要写技术博客?
    MySQL开发总结
    如何在Linux实现自动运行程序
    SSH无密码登录
    PHP版本MS17-010检测小脚本
    Msf的一些常用操作
    bypass safedog upload
    mysql拿webshell总结
    web端MSF搭建
    【漏洞复现】Tomcat CVE-2017-12615 远程代码执行漏洞
  • 原文地址:https://www.cnblogs.com/dcdcbigbig/p/9549445.html
Copyright © 2011-2022 走看看