bzoj2326 [HNOI2011]数学作业

题目链接:bzoj2326
题目大意:
给N,M。求出将1,2,…,N按顺序连在一起得到的数mod M的值。比如N是13的话,这个数就是12345678910111213。

题解:
矩乘%hyc
可以得知,答案ans=ans*10^(j的位数)+j,j=1 to N,再mod个M嘛。
于是我们可以构造一个↓这样的矩阵
×这里写图片描述
ans存的就是答案,而j就表示将要把j这个数连进去。
但因为j的位数会改变,即x就会改变。于是我们可以把位数相同的放在一起做一遍矩阵快速幂,然后修改a[0][0]这个位置的值,再继续搞就好了。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;

struct matrix
{
    LL a[3][3];int l,r;
    matrix() {memset(a,0,sizeof(a));}
};
matrix gg;LL n,mod;
matrix multt(matrix x,matrix y)
{
    matrix ret;int i,j,k;
    ret.l=x.l;ret.r=y.r;
    for (i=0;i<ret.l;i++)
     for (j=0;j<ret.r;j++)
     {
        for (k=0;k<y.l;k++)
          ret.a[i][j]+=x.a[i][k]*y.a[k][j];
        ret.a[i][j]%=mod;
     }
    return ret;
}
matrix qpow(matrix x,LL tt)
{
    matrix ret;ret.l=ret.r=3;
    ret.a[0][0]=ret.a[1][1]=ret.a[2][2]=1;
    while (tt)
    {
        if (tt&1) ret=multt(ret,x);
        x=multt(x,x);tt>>=1;
    }
    return ret;
}
int main()
{
    int i,tj;LL t,ww;
    scanf("%lld%lld",&n,&mod);
    memset(gg.a,0,sizeof(gg));
    gg.l=gg.r=3;t=n;tj=0;ww=1;
    gg.a[0][0]=10;gg.a[0][1]=gg.a[1][1]=gg.a[1][2]=gg.a[2][2]=1;
    while (t) tj++,t/=10;

    matrix ans;
    ans.l=3;ans.r=1;
    ans.a[0][0]=0;
    ans.a[1][0]=1;
    ans.a[2][0]=1;

    for (i=1;i<tj;i++)
    {
        matrix now=qpow(gg,ww*9);
        ans=multt(now,ans);
        gg.a[0][0]=(gg.a[0][0]*10)%mod;
        ww*=10;
    }
    matrix now=qpow(gg,n-ww+1);
    ans=multt(now,ans);
    printf("%lld\n",ans.a[0][0]);
    return 0;
}
posted @ 2017-03-09 13:58  OxQ  阅读(198)  评论(0编辑  收藏  举报