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

    题目描述

    小 C 数学成绩优异,于是老师给小 C 留了一道非常难的数学作业题:

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

    输入输出格式

    输入格式:

     

    从文件input.txt中读入数据,输入文件只有一行且为用空格隔开的两个正整数N和M,其中30%的数据满足1≤N≤1000000 ;100%的数据满足1≤N≤10^18 且1≤M≤10^9 .

     

    输出格式:

     

    输出文件 output.txt 仅包含一个非负整数,表示 Concatenate(1..NMod M 的值。

     

    输入输出样例

    输入样例#1: 
    13 13
    输出样例#1: 
    4

    Solution:

      本题矩阵快速幂。

      思路比较简单,范围内的10进制位权最多就18种。

      对于每种位权下的递推:$f[i]=f[i-1]*10^p+i$

      显然可以用矩阵去优化:

    $egin{bmatrix}f[i] & i+1 & 1end{bmatrix}$ $ imes$ $egin{bmatrix} 10^p &0 &0 \ 1& 1&0 \ 0& 1&1 end{bmatrix}$ $ ightarrow$ $egin{bmatrix}f[i+1]& i+2 & 1end{bmatrix}$

    代码:

    /*Code by 520 -- 10.8*/
    #include<bits/stdc++.h>
    #define il inline
    #define ll long long
    #define RE register
    #define For(i,a,b) for(RE int (i)=(a);(i)<=(b);(i)++)
    #define Bor(i,a,b) for(RE int (i)=(b);(i)>=(a);(i)--)
    #define clr(p) memset(&p,0,sizeof(p))
    using namespace std;
    ll n,mod,base[20];
    struct matrix{
        int r,c;ll a[3][3];
    };
    
    il matrix mul(matrix x,matrix y){
        matrix tp; clr(tp);
        tp.r=x.r,tp.c=y.c;
        For(i,0,x.r-1) For(j,0,y.c-1) For(k,0,x.c-1)
        tp.a[i][j]=(x.a[i][k]%mod*y.a[k][j]%mod+tp.a[i][j])%mod;
        return tp;
    }
    
    int main(){
        cin>>n>>mod;
        base[0]=1;
        For(i,1,18) base[i]=base[i-1]*10;
        matrix ans,tp; clr(ans),clr(tp);
        ans.r=1,ans.c=3; ans.a[0][0]=0,ans.a[0][1]=1,ans.a[0][2]=1;
        tp.r=tp.c=3; tp.a[1][0]=tp.a[1][1]=tp.a[2][1]=tp.a[2][2]=1;
        ll pos=0,k=0; int cnt=0;
        while(pos<n){
            if(n>=base[cnt+1]) k=base[cnt+1]-base[cnt];
            else k=n-base[cnt]+1;
            pos+=k;ans.a[0][1]=base[cnt]%mod;
            clr(tp),tp.r=tp.c=3;
            tp.a[0][0]=base[cnt+1]%mod;
            tp.a[1][0]=tp.a[1][1]=tp.a[2][1]=tp.a[2][2]=1;
            while(k){
                if(k&1) ans=mul(ans,tp);
                k>>=1,tp=mul(tp,tp);
            }
            cnt++;
        }
        cout<<ans.a[0][0];
        return 0;
    }
  • 相关阅读:
    20210815 图论模拟赛
    20210813 杂项の模拟赛
    20210812dp模拟赛
    20210811数据结构
    html问题记录20180514
    Oracle导出表空间的创建语句、导入、导出dmp文件
    浮动子div撑开父div的几种方法、给select赋值、zoom样式的含义、实现select下拉框readonly
    Fidder教程
    JQuery插件的写法和规范
    box-sizing position calc() @media
  • 原文地址:https://www.cnblogs.com/five20/p/9801092.html
Copyright © 2011-2022 走看看