zoukankan      html  css  js  c++  java
  • luogu3263/bzoj4002 有意义的字符串 (数学+矩阵快速幂)

    首先我们发现$frac{b+sqrt{d}}{2}$这个形式好像一元二次方程的求根公式啊(???反正我发现不了)

    然后我们又想到虽然这个东西不好求但是$(frac{b-sqrt{d}}{2})^n$好像挺好求的啊(???反正我想不到)(由题目给的范围,这玩意在(-1,1))

    于是把这个方程写出来:$x^2-b+frac{b^2-d}{4}=0$,设它的两根是$x_1=frac{b+sqrt{d}}{2} , x_2=frac{b-sqrt{d}}{2}$

    于是就是要求$lfloor x_1^n+x_2^n-x_2^n floor$

    我们把$x_1^n+x_2^n$单拎出来,分解一下,得到$x_1^n+x_2^n = (x_1+x_2)(x_1^{n-1}+x_2^{n-1}) - x_1x_2(x_1^{n-2}+x_2^{n-2}) $

    然后$x_1+x_2$和$x_1x_2$可以用韦达定理算,再把$x_1^i+x_2^i$设成f[i],就可以用矩阵快速幂优化了

    可以发现它是个整数,最后讨论一下$x_2^n$就行了

    (模数巨大,不光要用龟速乘,还要用unsigned long long)

     1 #include<bits/stdc++.h>
     2 #define CLR(a,x) memset(a,x,sizeof(a))
     3 using namespace std;
     4 typedef long long ll;
     5 typedef unsigned long long ull;
     6 typedef pair<int,int> pa;
     7 const ull P=7528443412579576937;
     8 
     9 inline ll rd(){
    10     ll x=0;char c=getchar();int neg=1;
    11     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
    12     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    13     return x*neg;
    14 }
    15 
    16 ull fmul(ull a,ull b){
    17     ull re=0;
    18     while(b){
    19         if(b&1) re=(re+a)%P;
    20         a=(a+a)%P,b>>=1;
    21     }return re;
    22 }
    23 
    24 ull b,d,n;
    25 
    26 ull fpow(ull x){
    27     ull f[2];f[0]=b,f[1]=2;
    28     ull m[2][2],tmp[2][2];
    29     m[0][0]=b,m[0][1]=1,m[1][0]=(d-b*b)/4,m[1][1]=0;
    30     while(x){
    31         if(x&1){
    32             CLR(tmp,0);
    33             for(int i=0;i<=1;i++){
    34                 for(int j=0;j<=1;j++){
    35                     tmp[0][i]=(tmp[0][i]+fmul(f[j],m[j][i]))%P;
    36                 }
    37             }
    38             f[0]=tmp[0][0],f[1]=tmp[0][1];
    39         }
    40         CLR(tmp,0);
    41         for(int i=0;i<=1;i++){
    42             for(int j=0;j<=1;j++){
    43                 for(int k=0;k<=1;k++){
    44                     tmp[i][j]=(tmp[i][j]+fmul(m[i][k],m[k][j]))%P;
    45                 }
    46             }
    47         }
    48         memcpy(m,tmp,sizeof(m));
    49         x>>=1;
    50     }return f[0];
    51 }
    52 
    53 int main(){
    54     //freopen("","r",stdin);
    55     int i,j,k;
    56     b=rd(),d=rd(),n=rd();
    57     if(n==0) printf("1
    ");
    58     else{
    59         ull ans=fpow(n-1);
    60         if(!(n&1)&&d!=b*b) ans=(P+ans-1)%P;
    61         printf("%lld
    ",ans);
    62     }
    63 
    64     return 0;
    65 }
  • 相关阅读:
    Sql Server2012连接不上问题
    WinForm的App.config写法
    (原)centos 防火墙开放端口命令
    Linux下rsync的用法
    Centos7下部署minio
    arthas简单使用
    在Docker中运行MinIO单点模式
    中台是什么
    Kubernetes K8S之Ingress详解与示例
    Rancher2.x平台搭建与使用
  • 原文地址:https://www.cnblogs.com/Ressed/p/9965412.html
Copyright © 2011-2022 走看看