题目描述

小 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≤1018且1≤M≤109.

输出格式:
输出文件 output.txt 仅包含一个非负整数,表示 Concatenate (1 .. N) Mod M 的值。

输入输出样例

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

首先写出递推关系式:令s[i]为前i个数连接得到的数,c(i)表示i的位数,有s[i]= 10^c(i)+s[i-1]+i;

c(i)随i变化,无法在转移矩阵T中表示。如果c(i)固定,就可以套用矩阵快速幂的方法进行优化了!

考虑位数随着i的变化最多只会变化18次,因此可以按位数分段进行矩阵快速幂。

枚举位数,那么有:
{10^k,0,0
{f[i-1],i-1,1}* 1, 1 ,0 = {f[i],i,1}
1, 1 ,1}
这里在状态矩阵中加了一个永远为1的值,用于辅助i每次加一。

将多位数按每次加数时前一个数所乘的10的个数分为10-99,100-999。。。的数字段,方便进行矩阵乘法 。

实现代码时套模拟矩阵乘法模板和快速幂模板即可。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#define ll long long
using namespace std;
ll n,m,S[3][3]={},T[3][3]={};
void mmul(ll a[3][3],ll b[3][3],ll s[3][3])//模拟矩阵乘法
{
    ll tmp[3][3]={};//此处a和s是同一数组,必须开一个数组作中转站(而不是像在重载运算符中结果数组是独立的,不受乘数影响)
    for(int i=0;i<3;i++)
       for(int j=0;j<3;j++)
          for(int k=0;k<3;k++)
             tmp[i][j]=(tmp[i][j]+(a[i][k]%m)*(b[k][j]%m))%m;//两个长整型数相乘,一定要分别取余,否则会爆负数(超范围了)
    for(int i=0;i<3;i++)
       for(int j=0;j<3;j++)
          s[i][j]=tmp[i][j];//在不影响乘数的前提下得出结果
}
void cal(ll t,ll last)
{
    memset(T,0,sizeof(T));
    T[0][0]=t;//每次加数时前一个数应进的位数
    T[1][0]=T[1][1]=T[2][0]=T[2][1]=T[2][2]=1;
    ll y=last-t/10+1;//y决定在该数字段下加数的次数
    while(y)//快速幂模板
    {        if(y&1)mmul(S,T,S);//模拟矩阵乘法
        mmul(T,T,T);
        y>>=1;
    }
}
int main()
{
    scanf("%lld%lld",&n,&m);
    S[0][0]=S[1][1]=S[2][2]=1;//初始化
    ll t=10;
    while(n>=t)
    {        cal(t,t-1);//将多位数按每次加数时前一个数所乘的10的个数分为10-99,100-999。。。的数字段,方便进行矩阵乘法
        t*=10;
    }
    cal(t,n);//如果n<10,就说明每次加数时只要进一位即可
    printf("%lld",S[2][0]);
    return 0;
}

转载于:https://www.cnblogs.com/yanshannan/p/7392294.html

洛谷P3216 [HNOI2011]数学作业相关推荐

  1. 洛谷 P3216 [HNOI2011]数学作业

    PS:如果读过题了可以跳过题目描述直接到题解部分 提交链接:洛谷 P3216 [HNOI2011]数学作业 题目 题目描述 小 C 数学成绩优异,于是老师给小 C 留了一道非常难的数学作业题: 给定正 ...

  2. BZOJ 2326: [HNOI2011]数学作业( 矩阵快速幂 )

    BZOJ先剧透了是矩阵乘法...这道题显然可以f(x) = f(x-1)*10t+x ,其中t表示x有多少位. 这个递推式可以变成这样的矩阵...(不会用公式编辑器...), 我们把位数相同的一起处理 ...

  3. 洛谷试炼场-简单数学问题-二分查找

    洛谷试炼场-简单数学问题 P1147 连续自然数和 题解: 本题给定一个数n,求连续自然数的和为n,用一个前缀数组,low_bound,upper_bound,查找是否是同一个数.O(nlog(n)) ...

  4. bzoj 2326: [HNOI2011]数学作业(矩阵快速幂)

    2326: [HNOI2011]数学作业 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 2249  Solved: 1301 [Submit][St ...

  5. HNOI2011 数学作业

    先上一下题目吧 HNOI2011 数学作业 Problem 小 C 数学成绩优异,于是老师给小 C 留了一道非常难的数学作业题: 给定正整数 N 和 M ,要求计算 Concatenate(1..N) ...

  6. 洛谷P2433 小学数学 N 合一

    写完了这道题结果脑子断电把浏览器关了......打开一看 没保存 寄 传送门:[深基1-2]小学数学 N 合一 - 洛谷 第一题 第二题 第三题 这几道题没啥好说的,直接输出就彳亍了 cout < ...

  7. bzoj 2326: [HNOI2011]数学作业

    Description 小 C 数学成绩优异,于是老师给小 C 留了一道非常难的数学作业题:给定正整数 N 和 M 要求计算 Concatenate (1 .. N) Mod M 的值,其中 Conc ...

  8. [HNOI2011]数学作业

    题目描述 小 C 数学成绩优异,于是老师给小 C 留了一道非常难的数学作业题: 给定正整数 N 和 M,要求计算 Concatenate (1 .. N) Mod M 的值,其中 Concatenat ...

  9. [洛谷]P1978 集合 (#数学 -1.3)(#STL -1.1)

    题目描述 集合是数学中的一个概念,用通俗的话来讲就是:一大堆数在一起就构成了集合.集合有如 下的特性: •无序性:任一个集合中,每个元素的地位都是相同的,元素之间是无序的. •互异性:一个集合中,任何 ...

  10. [HNOI2011]数学作业 分段矩阵乘法

    给n,问123--n这个数字串模m的数值,n<=1e18 对于0-9,10-99,这些数字之间都满足f(n)=f(n-1)*10^c,c定值 这每一段都可以做矩阵快速幂 ,存一下[f(n),n, ...

最新文章

  1. 我用 PyTorch 复现了 LeNet-5 神经网络(自定义数据集篇)!
  2. 【Python基础】使用列表、字典和集合生成式来缩短代码
  3. Java sqlite事务方法,Java SQLiteDatabase.insert方法代码示例
  4. maven项目发布到tomcat里lib包没有发布的问题
  5. git 删除本地和远程分支_如何在本地和远程删除Git分支
  6. Mac安装masscan【亲测有用】
  7. 'yasm' 不是内部或外部命令
  8. 真不是炼丹,务实敢为的 MoCo v3
  9. 如何让字体大小12px
  10. python 去除字典列表中的重复字典
  11. 计算机课件白板培训,希沃白板使用教学,直接导入PPT课件并修改
  12. Axure(软件下载安装与使用)——成为产品经理的必修课
  13. matlab二重积分计算程序,MATLAB在二重积分计算中的应用
  14. slf4j没有在linux中生成日志,slf4j日志记录问题 - 未生成日志文件
  15. 【数据库】ER图进行描述某系统之学习七
  16. WebGL简易教程(五):图形变换(模型、视图、投影变换)
  17. switchhosts的作用
  18. linux修改宽带拨号密码,linux 下 adsl 拨号设置
  19. (自适应手机移动端)高端响应式路由器电子产品公司网站源码
  20. XRP瑞波JAVA调用(离线签名)

热门文章

  1. 【计算机视觉入门案例】手写数字识别:Keras深度学习库
  2. PHP设置脚本最大执行时间的三种方法
  3. python-format函数
  4. maven(6)------maven坐标分析
  5. locate-updatedb命令检索不全
  6. Python输入和输出
  7. 排序算法入门之堆排序
  8. MYSQL 4种插入数据的方式比较
  9. SQL Server 2008安装
  10. 用友U8对账不平,对账错误简单处理方法