BZOJ2326: [HNOI2011]数学作业

来源:互联网 发布:项目经理必备软件 编辑:程序博客网 时间:2024/04/29 10:01

Portal

这里写图片描述

很容易得到递推式f[i]=f[i1]10k+i (10k1<=i<10k)
数据范围达到1018,所以很容易想到用矩阵优化。
构造矩阵:

(f[i]i1)10k11011001

然后分段开开心心的分段矩乘啦。注意边界。

【代码】

#include <iostream>#include <cstdio>#include <algorithm>#define N 10005using namespace std;typedef long long ll;ll read(){    ll x=0,f=1;char ch=getchar();    while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}    while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}    return x*f;}class matrix{    public:        int x,y;        ll v[4][4];}a,b,s; ll n,tmp=1;int mod,m;ll Qmul(ll x,ll y){    ll rtn=0;    while(y)    {        if(y&1) rtn=(rtn+x)%mod;        x=(x+x)%mod;y>>=1;    }    return rtn;}matrix Matrix_Mul(matrix aa,matrix bb){    matrix rtn;    rtn.x=aa.x,rtn.y=bb.y;    for(int i=1;i<=aa.x;i++)    for(int j=1;j<=aa.y;j++)    {        rtn.v[i][j]=0;        for(int k=1;k<=bb.y;k++)            rtn.v[i][j]=(rtn.v[i][j]+Qmul(aa.v[i][k],bb.v[k][j]))%mod;    }    return rtn;}void Matrix_Pow(ll num){    for(int i=1;i<=3;i++)    for(int j=1;j<=3;j++) s.v[i][j]=b.v[i][j];    s.x=s.y=3;    while(num)    {        if(num&1) a=Matrix_Mul(a,s);        s=Matrix_Mul(s,s);num>>=1;    }}int main(){    n=read(),mod=read();    a.v[1][3]=1;a.x=1,a.y=3;    b.x=b.y=3;    for(int i=1;i<=3;i++)    for(int j=1;j<=i;j++) b.v[i][j]=1;    for(;;)    {        b.v[1][1]*=10;        if(tmp*10-1>=n)        {            Matrix_Pow(n-tmp+1);            break;        }        Matrix_Pow(tmp*10-tmp);tmp*=10;    }     printf("%lld\n",a.v[1][1]);    return 0;}
0 0
原创粉丝点击