题目描述

小 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;
}

洛谷P3216 [HNOI2011]数学作业的更多相关文章

  1. 洛谷P3216 [HNOI2011] 数学作业 [矩阵加速,数论]

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

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

    最近学了矩阵,kzj大佬推荐了我这一道题目. 乍一眼看上去,没看出是矩阵,就随便打了一个暴力,30分. 然后仔细分析了一波,发现蛮简单的. 结果全wa了,先看看下面的错误分析吧! 首先,设f[n]为最 ...

  3. [bzoj2326] [洛谷P3216] [HNOI2011] 数学作业

    想法 最初的想法就是记录当前 \(%m\) 值为cur,到下一个数时 \(cur=cur \times 10^x + i\) n这么大,那就矩阵乘法呗. 矩阵乘法使用的要点就是有一个转移矩阵会不停的用 ...

  4. [luogu P3216] [HNOI2011]数学作业

    [luogu P3216] [HNOI2011]数学作业 题目描述 小 C 数学成绩优异,于是老师给小 C 留了一道非常难的数学作业题: 给定正整数 N 和 M,要求计算 Concatenate (1 ...

  5. P3216 [HNOI2011]数学作业 (矩阵快速幂)

    P3216 [HNOI2011]数学作业 题目描述 小 C 数学成绩优异,于是老师给小 C 留了一道非常难的数学作业题: 给定正整数 NN 和 MM ,要求计算 Concatenate (1 .. N ...

  6. P3216 [HNOI2011]数学作业

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

  7. bzoj2326: [HNOI2011]数学作业

    矩阵快速幂,分1-9,10-99...看黄学长的代码理解...然而他直接把答案保存在最后一行(没有说明...好吧应该是我智障这都不知道... #include<cstdio> #inclu ...

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

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

  9. 洛谷试炼场-简单数学问题-P1403 [AHOI2005]-因数

    洛谷试炼场-简单数学问题 P1403 [AHOI2005]约数研究 Description 科学家们在Samuel星球上的探险得到了丰富的能源储备,这使得空间站中大型计算机"Samuel I ...

随机推荐

  1. 使用 PHP + shell 生成 一键设置权限的脚本。

    linux 系统 支持PHP脚本一键设置环境.shell脚本一键设置环境.那么 我今天 使用 PHP  + shell 生成 一键设置权限的脚本. 举例子:linux服务器 一键配置discuz网站环 ...

  2. awk,grep,sed文本格式化处理

    一.awk取列 [root@web01 ~]# cat /etc/passwd|awk -F ':' '{print $1"\t\t"$7}' ###-F指定分隔符 root /b ...

  3. ResNet,DenseNet

    目录 ResNet BOOM Why call Residual? 发展史 Basic Block Res Block ResNet-18 DenseNet ResNet 确保20层能训练好的前提下, ...

  4. django 使用框架下auth.models自带的User进行扩展增加字段

    需要改动三个地方: 1.models.py   创建模型User,并继承原模型类AbstraUser(在此处我增加了一个新的字段手机号) from django.db import models # ...

  5. LINUX系统---初级相关操作和知识

    LINUX系统的初级,从安装LINUX开始,到处理简单的运维问题.搭建各种服务.解决网路问题.缓解服务器压力,写简单的shell脚本. 我们从基本的入门开始搞事情: 安装LINUX系统 对磁盘的使用 ...

  6. Hadoop安装与配置

    Hadoop介绍 上面是官方介绍,翻一下来总结一句话就是:Hadoop是一个高可用,用于分布式处理大规模计算的工具. Hadoop1.2 下载 . Hadoop1.2 安装 1. 安装jDK 2. 配 ...

  7. NOI模拟(3.6)Assignment

    Description 随机生成一个长度为m且每个元素都为1~n之间的整数的单调不下降序列~(即序列的(i>1)都不小于),(随机生成指每一种可能的序列都等概率被生成).请问这个序列的众数出现次 ...

  8. wait和waitpid函数

    来源:http://hohahohayo.blog.163.com/blog/static/120816010200971210230362/ wait(等待子进程中断或结束)表头文件     #in ...

  9. JVM(三):深入分析Java字节码-上

    JVM(三):深入分析Java字节码-上 字节码文章分为上下两篇,上篇也就是本文主要讲述class文件存在的意义,以及其带来的益处.并分析其内在构成之一 ---字节码,而下篇则从指令集方面着手,讲解指 ...

  10. 镜像二叉树——剑指Offer

    https://www.nowcoder.net/practice/564f4c26aa584921bc75623e48ca3011?tpId=13&tqId=11171&tPage= ...