【bzoj2326】[HNOI2011]数学作业 矩阵乘法
题目描述
题解
矩阵乘法
考虑把相同位数的数放到一起处理:
设有$k$位的数为$[l,r]$,那么枚举从大到小的第$i$个数(即枚举$r-i+1$),考虑其对$Concatenate(l..r)$的贡献:
$v_i=(r-i+1)10^{k(i-1)}$
所以要求的就是:
$\sum\limits_{i=1}^{r-l+1}(r-i+1)10^{k(i-1)}\mod m\ =\ \sum\limits_{i=0}^{r-l}(r-i)10^{ki}\mod m$
这个式子可以使用矩阵乘法解决。具体方法:
$\begin{bmatrix}(r-i)10^{ki}&10^{ki}&sum_{i-1}\end{bmatrix}*\begin{bmatrix}10^k&0&1\\-10^k&10^k&0\\0&0&1\end{bmatrix}=\begin{bmatrix}(r-i-1)10^{k(i+1)}&10^{k(i+1)}&sum_i\end{bmatrix}$
然后再乘上$10^{该位后面的位数}$即为它们对答案的贡献。把所有位数的数的贡献加起来即为答案。
注意需要unsigned long long。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef unsigned long long ull;
int m;
struct data
{
ull v[3][3];
data(ull x = 0) {memset(v , 0 , sizeof(v)) , v[0][0] = v[1][1] = v[2][2] = x;}
ull *operator[](int a) {return v[a];}
data operator*(data a)
{
data ans;
int i , j , k;
for(i = 0 ; i < 3 ; i ++ )
for(j = 0 ; j < 3 ; j ++ )
for(k = 0 ; k < 3 ; k ++ )
ans[i][j] = (ans[i][j] + v[i][k] * a[k][j]) % m;
return ans;
}
}a;
data pow(data x , ull y)
{
data ans(1);
while(y)
{
if(y & 1) ans = ans * x;
x = x * x , y >>= 1;
}
return ans;
}
ull pow(ull x , ull y)
{
ull ans = 1;
while(y)
{
if(y & 1) ans = ans * x % m;
x = x * x % m , y >>= 1;
}
return ans;
}
int main()
{
ull i , j , n , now = 1 , ans = 0;
scanf("%llu%d" , &n , &m);
for(i = 1000000000000000000ull , j = 19 ; i ; i /= 10 , j -- )
{
if(n < i) continue;
a[0][0] = a[1][1] = i % m * 10 % m , a[1][0] = (m - a[0][0]) % m , a[0][2] = a[2][2] = 1 , a[0][1] = a[1][2] = a[2][0] = a[2][1] = 0;
a = pow(a , n - i + 1);
ans = (ans + (n % m * a[0][2] % m + a[1][2]) * now) % m , now = now * pow(10 , j * (n - i + 1)) % m , n = i - 1;
}
printf("%llu\n" , ans);
return 0;
}
【bzoj2326】[HNOI2011]数学作业 矩阵乘法的更多相关文章
- [BZOJ2326] [HNOI2011] 数学作业 (矩阵乘法)
Description Input Output Sample Input Sample Output HINT Source Solution 递推式长这样:$f[n]=f[n-1]*10^k+n$ ...
- BZOJ 2326: [HNOI2011]数学作业(矩阵乘法)
传送门 解题思路 NOIp前看到的一道题,当时想了很久没想出来,NOIp后拿出来看竟然想出来了.注意到有递推\(f[i]=f[i-1]*poww[i]+i\),\(f[i]\)表示\(1-i\)连接起 ...
- BZOJ-2326 数学作业 矩阵乘法快速幂+快速乘
2326: [HNOI2011]数学作业 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 1564 Solved: 910 [Submit][Statu ...
- BZOJ 2326: [HNOI2011]数学作业( 矩阵快速幂 )
BZOJ先剧透了是矩阵乘法...这道题显然可以f(x) = f(x-1)*10t+x ,其中t表示x有多少位. 这个递推式可以变成这样的矩阵...(不会用公式编辑器...), 我们把位数相同的一起处理 ...
- bzoj2326: [HNOI2011]数学作业
矩阵快速幂,分1-9,10-99...看黄学长的代码理解...然而他直接把答案保存在最后一行(没有说明...好吧应该是我智障这都不知道... #include<cstdio> #inclu ...
- [HNOI2011]数学作业 --- 矩阵优化
[HNOI2011]数学作业 题目描述: 小 C 数学成绩优异,于是老师给小 C 留了一道非常难的数学作业题: 给定正整数 N 和 M ,要求计算\(Concatenate(1..N)\; Mod\; ...
- 【BZOJ2326】【HNOI2011】数学作业 [矩阵乘法][DP]
数学作业 Time Limit: 10 Sec Memory Limit: 128 MB[Submit][Status][Discuss] Description Input 输入文件只有一行为用空 ...
- 洛谷P3216 [HNOI2011] 数学作业 [矩阵加速,数论]
题目传送门 数学作业 题目描述 小 C 数学成绩优异,于是老师给小 C 留了一道非常难的数学作业题: 给定正整数 N和 M,要求计算 Concatenate (1 .. N)Mod M 的值,其中 C ...
- bzoj2326:[HNOI2011]数学作业(分段矩阵乘法)
题目大意:输入n(n<=10^18)和m,将1~n的整数连起来模m输出,比如n=13则输出12345678910111213模m的数. 设f[i]为1~i整数连起来模m的数,i的位数为k,则有f ...
随机推荐
- round函数在oracle和mysql中用法
1.oracle和mysql通用方法 #round(字段1,小数位数) 四舍五入select round('11.123456',4);结果:11.1235 2.mysql的另外2种保留小数位数方法# ...
- 通过Ambari2.2.2部署HDP大数据服务
node1 amari-server node2 amari-agent namenode1,datanode,resourcemanager,zk node3 amari-agent namen ...
- js判断是否为数字
function isNumber(value) { var patrn = /^(-)?\d+(\.\d+)?$/; if (patrn.exec(value) == null || value = ...
- connect() to unix:/var/run/php-fpm.sock failed (11: Resource temporarily unavailable)
nginx + php做服务,在高并发的时候会出现一些错误 connect() to unix:/var/run/php-fpm.sock failed (11: Resource temporar ...
- 自己动手编写 Dockerfile 构建自定义的Jenkins
1.构建jenkins 镜像 vim Dockerfile FROM jenkins USER root ARG dockerGid=999 RUN echo "docker:x:${d ...
- GDOI DAY1游记
今天,是本蒟蒻的第一次参加GDOI,真激动! 今天,是GDOI第一天,昨天熬夜打代码,今天早上状态十分不好,于是... 进入了考场,叫我们自由打一会代码,于是...打了一坨AC机,重要的是错了(额.. ...
- 用filter()筛选出素数
'use strict'; function get_primes(arr) { return arr.filter(function isPrime(number) { if (typeof num ...
- javascript实现浏览器管理员工具鼠标获取Html元素 并生成 xpath
javascript实现浏览器管理员工具鼠标获取Html元素 并生成 xpath 看看标题就被吓尿了,够长吧.让我们看看到底是个什么玩意.. 直接上图: 就是这个东东了,做为一个写爬虫的,有必要了解下 ...
- python2.7练习小例子(二十)
20):题目:猴子吃桃问题:猴子第一天摘下若干个桃子,当即吃了一半,还不瘾,又多吃了一个第二天早上又将剩下的桃子吃掉一半,又多吃了一个.以后每天早上都吃了前一天剩下的一半零一个.到第10天早上 ...
- python的初体验
最近由于毕业答辩,导致一些博客没有更新,见谅,今天我们开始一些新的内容 1.python的注释 单行注释:# 多行注释: ''' 这是多行注释 我们可以在里面写很多很多的行 ''' 2.编码风格 #c ...