Bzoj2326:HNOI2011-数学作业

来源:互联网 发布:石狮淘宝培训中心 编辑:程序博客网 时间:2024/06/13 23:23

题面

思路

Dp应该是比较显然的
F(N) 表示N的答案
k 表示N的位数

F(N)=F(N1)10k+N

考虑矩乘优化
F(N)N1=10k00110111F(N1)N11

但是位数会有改变
可以将位数不同的几段分开矩乘

代码

#include <cmath>#include <algorithm>using namespace std;typedef long long ll;char ch;bool fl;inline void read(int &a){    for(fl=0,ch=getchar();ch<'0'||ch>'9';ch=getchar()) fl^=(ch=='-');    for(a=0;ch>='0'&&ch<='9';ch=getchar())a=(a<<3)+(a<<1)+(ch^'0');    if(fl)a=-a;}const int S=3;const int LOG=19;ll N,K;int Mods,k=0;struct Matrix{    int p[S][S];};const Matrix First=(Matrix){{{1,0,0},{0,1,0},{0,0,1}}};void Mul(Matrix &Ans,Matrix b){    Matrix a;    for(int i=0;i<S;i++)        for(int j=0;j<S;j++){            a.p[i][j]=Ans.p[i][j];            Ans.p[i][j]=0;        }    for(int i=0;i<S;i++)        for(int k=0;k<S;k++)                    for(int j=0;j<S;j++){                Ans.p[i][j]+=(ll)a.p[i][k]*b.p[k][j]%Mods;                if(Ans.p[i][j]>=Mods)Ans.p[i][j]-=Mods;             }}Matrix Power(Matrix A,ll p){    Matrix Ans=First;    for(;p;p>>=1){        if(p&1)Mul(Ans,A);        Mul(A,A);    }    return Ans;}int main(){    ll Pow[LOG];    Matrix Trans=(Matrix){{{1,1,1},{0,1,1},{0,0,1}}},Res=First,Ans;    Pow[0]=9;    for(int i=1;i<LOG;i++)Pow[i]=(Pow[i-1]+(Pow[i-1]<<2))<<1;    for(scanf("%lld%d",&N,&Mods);N;N-=K,k++){        K=min(N,Pow[k]);        Trans.p[0][0]+=Pow[k]%Mods;        if(Trans.p[0][0]>=Mods)Trans.p[0][0]-=Mods;        Ans=Power(Trans,K);        Mul(Ans,Res);        Res=Ans;    }    printf("%d",Res.p[0][2]);    return 0;}
原创粉丝点击