zoukankan      html  css  js  c++  java
  • codevs 2314 数学作业(矩阵乘法)

    2314 数学作业

     

    2011年省队选拔赛湖南

     时间限制: 1 s
     空间限制: 128000 KB
     题目等级 : 大师 Master
     
     
    题目描述 Description

    小 C 数学成绩优异,于是老师给小 C 留了一道非常难的数学作业题: 给定正整数 N 和 M ,要求计算 Concatenate (1 .. N ) Mod M 的值,其中Concatenate (1 .. N ) 是将所有正整数 1, 2, …, N 顺序连接起来得到的数。例如, N = 13, Concatenate (1 .. N ) = 12345678910111213. 小 C 想了大半天终于意识到这是一道不可能手算出来的题目,于是他只好向你求助,希望 你能编写一个程序帮他解决这个问题。

    输入描述 Input Description

    只有一行 为用空格隔开的两个正整数 N 和 M

    输出描述 Output Description

    仅包含一个非负整数,表示 Concatenate (1 .. N ) Mod M 的值

    样例输入 Sample Input

    13 13

    样例输出 Sample Output

    4

    数据范围及提示 Data Size & Hint

    其中 30%的数据满足1≤ N ≤1000000;100%的数据满足1≤ N ≤1018且1≤ M ≤109

    /*
    矩阵乘法
    f[i]=f[i-1]*10的i的长度次方+i
    i的长度是不同的 没法直接矩阵乘法
    按i的长度分情况用矩阵乘法 
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define LL long long
    using namespace std;
    LL n,p;
    LL a[5][5],b[5][5],c[5][5],f[5][5]; 
    LL init()
    {
        LL x=0,f=1;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    LL slow_mul(LL a,LL b)
    {
        LL ret=0;
        while(b)
        {
            if(b&1)ret+=a,ret%=p,b--;
            a<<=1;a%=p;b>>=1;
        }
        return ret;
    }
    LL mul(LL a[5][5],LL b[5][5])
    {
        for(LL i=1;i<=3;i++)
        {
            for(LL j=1;j<=3;j++)
            {
                LL x=0;
                for(LL k=1;k<=3;k++)
                x=(x+slow_mul(a[i][k],b[k][j]))%p;
                c[i][j]=x;
            }
        }
        for(LL i=1;i<=3;i++)
        {
            for(LL j=1;j<=3;j++)
            a[i][j]=c[i][j];
        }
    }
    void pow(LL x)
    {
        if(x==1)
        {
            memcpy(a,b,sizeof(b));
            return;
        }
        pow(x/2);
        mul(a,a);
        if(x&1)mul(a,b);
    }
    int main()
    {
        LL i,j,k; 
        n=init();p=init();
        f[1][2]=1;f[1][3]=1;
        b[2][1]=1;b[2][2]=1;
        b[3][2]=1;b[3][3]=1;
        for(i=10;i<=n;i*=10)
        {
            b[1][1]=i%p;
            pow(i-i/10);
            mul(f,a);
        }
        b[1][1]=i%p;
        pow(n-i/10+1);
        mul(f,a);
        cout<<f[1][1]<<endl;
        return 0;
    }
  • 相关阅读:
    ado GetRows
    mysql数据库学习——2,数据库的选定,创建,删除和变更
    mysql数据库学习——4,完整性约束
    mssql数据集操作方法
    mysql数据库学习——1,获取原数据
    mysql书籍
    php学习——smarty
    mysql数据库学习——5,数据类型,字符集和校对
    phpcms——评论内容字符控制
    phpcms权限问题,父栏目权限应用到子栏目不管用
  • 原文地址:https://www.cnblogs.com/dingmenghao/p/6006880.html
Copyright © 2011-2022 走看看