zoukankan      html  css  js  c++  java
  • BZOJ2326: [HNOI2011]数学作业

    BZOJ2326: [HNOI2011]数学作业

    Description

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

    Input

    只有一行且为用空格隔开的两个正整数N和M,1≤N≤10^18且1≤M≤10^9.

    Output

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

    Sample Input

    13 13

    Sample Output

    4

    题解Here!
    看到$N<=10^{18}$,不是矩乘就是跟$N$无关。
    当然这题不可能与$N$无关,那就矩乘。
    首先,要推出一个线性递推的式子。
    然而一开始我把题目看错了,推出了这样一个式子:$$f(i)=f(i-1) imes 10+i$$
    觉得这不是沙茶题吗?
    这是一个$flag$。。。
    放到矩阵里就是:$$f(i)=f(i-1) imes 10+i-1+1$$
    造出矩阵:$$left[egin{array}{}10&0&0\1&1&0\1&1&1 end{array} ight]$$
    我沾沾自喜的交了上去,以为能$1A$。
    然后$WAquad 0$。
    $flag$不能乱立啊。。。
    回头看题,我发现我就是个$zz$。。。
    递推式应该是:$$f(i)=f(i-1) imes 10^k+i, ext{k为i的位数}$$
    继续造矩阵:$$left[egin{array}{}10^k&0&0\1&1&0\1&1&1 end{array} ight]$$
    $10^k$的计算要分段,这段的实现可能会让你抓狂,忍住!慢慢改。
    这样我们可以求出:$$Concatenate(1...9),Concatenate(10...99),Concatenate(100...999),...,Concatenate(10^k,N)$$
    因为$k$的取值只有不到$20$种,我们可以直接枚举处理。
    供应一组数据:
    Input       948177742992423376 819143553
    Output      578278753
    

    附代码:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    using namespace std;
    int k=0;
    long long n,mod;
    struct node{
        long long a[5][5];
        friend node operator +(node x,int k){
            x.a[1][1]=1;
            for(int i=1;i<=k;i++)x.a[1][1]*=10LL;
            x.a[1][1]%=mod;
            x.a[1][2]=x.a[1][3]=x.a[2][3]=0;
            x.a[2][1]=x.a[2][2]=x.a[3][1]=x.a[3][2]=x.a[3][3]=1;
            return x;
        }
        friend node operator *(const node x,const node y){
            node ret;
            for(int i=1;i<=3;i++)
            for(int j=1;j<=3;j++){
                ret.a[i][j]=0;
                for(int k=1;k<=3;k++){
                    ret.a[i][j]+=x.a[i][k]%mod*y.a[k][j]%mod;
                    ret.a[i][j]%=mod;
                }
            }
            return ret;
        }
        friend node operator ^(node x,long long k){
            node s;
            for(int i=1;i<=3;i++)
            for(int j=1;j<=3;j++)
            s.a[i][j]=(i==j?1:0);
            while(k){
                if(k&1)s=s*x;
                x=x*x;
                k>>=1;
            }
            return s;
        }
    }base[20],ans;
    inline long long read(){
    	long long date=0,w=1;char c=0;
    	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
    	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
    	return date*w;
    }
    long long mexp(long long a,long long b){
        long long s=1;
        while(b){
            if(b&1)s=s*a;
            a*=a;
            b>>=1;
        }
        return s;
    }
    void work(){
        for(int i=1;i<=3;i++)
        for(int j=1;j<=3;j++)
        ans.a[i][j]=(i==j?1:0);
        for(int i=1;i<=k;i++)ans=ans*base[i];
        printf("%lld
    ",ans.a[3][1]);
    }
    void init(){
        long long x;
        x=n=read();mod=read();
        while(x){x/=10LL;k++;}
        for(int i=1;i<k;i++){
            base[i]=base[i]+i;
            base[i]=base[i]^(mexp(10,i-1)*9LL);
        }
        base[k]=base[k]+k;
        base[k]=base[k]^(n-mexp(10,k-1)+1);
    }
    int main(){
        init();
        work();
        return 0;
    }
    
  • 相关阅读:
    2019-9-2-简单搭建自己的博客
    2018-7-15-WPF-在-DrawingContext-的-push-如何使用
    2018-7-15-WPF-在-DrawingContext-的-push-如何使用
    2019-7-3-Roslyn-理解-msbuild-的清理过程
    2019-7-3-Roslyn-理解-msbuild-的清理过程
    MySQL数据库事务详解
    求一个Map中最大的value值,同时列出键,值
    Struts1入门实例(简单登录)
    java字符流操作flush()方法及其注意事项
    HDU 1874 畅通工程续 2008浙大研究生复试热身赛(2)
  • 原文地址:https://www.cnblogs.com/Yangrui-Blog/p/9484792.html
Copyright © 2011-2022 走看看