bzoj2326【HNOI2011】数学作业

2326: [HNOI2011]数学作业

Time Limit: 10 Sec  Memory Limit: 128 MB

Submit: 1648  Solved: 972

[Submit][Status][Discuss]

Description

(f[n])(10^k  1    1)(f[n-1])

( n )=(0      1    1)( n-1 )

( 1 ) (0      0    1)(  1  )

然后分段矩阵乘法。这道题调了整整一晚上,忘记每一步运算都取模,这道题很容易超过long long。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
using namespace std;
ll n,m;
struct matrix
{
	ll f[4][4];
	matrix(){memset(f,0,sizeof(f));}
	friend matrix operator *(const matrix &a,const matrix &b)
	{
		matrix c;
		F(i,1,3) F(j,1,3) F(k,1,3) c.f[i][j]=(c.f[i][j]%m+a.f[i][k]%m*b.f[k][j]%m)%m;
		return c;
	}
}ans,tmp;
inline void calc(ll t,ll x)
{
	memset(tmp.f,0,sizeof(tmp.f));
	tmp.f[1][1]=t%m;
	tmp.f[1][2]=tmp.f[1][3]=tmp.f[2][2]=tmp.f[2][3]=tmp.f[3][3]=1;
	for(ll y=x-t/10+1;y;y>>=1,tmp=tmp*tmp) if (y&1) ans=tmp*ans;
}
int main()
{
	scanf("%lld%lld",&n,&m);
	memset(ans.f,0,sizeof(ans.f));
	F(i,1,3) ans.f[i][i]=1;
	ll t=10;
	while (n>=t)
	{
		calc(t,t-1);
		t*=10;
	}
	calc(t,n);
	printf("%lld\n",ans.f[1][3]);
	return 0;
}
时间: 2024-10-10 05:31:52

bzoj2326【HNOI2011】数学作业的相关文章

BZOJ2326 HNOI2011 数学作业 矩阵乘法

题意:求12345……101112……(N-1)N mod M的值(被模数就是1-N顺次连接起来). 题解:丧病的数学老师,看自己写的题解都看不懂了QAQ,首先设${f_i}$=前i个数连接起来 mod M的值,然后按位数不断转移,也就是说,假定当前要增加的数i最高位是10^k,那么\[{f_i} = ({10^{k + 1}}{f_{i - 1}} + i)\bmod M\] 所以\[\left( {\begin{array}{*{20}{c}}{{f_{{{10}^{k + 1}} - 1}

bzoj2326 [HNOI2011]数学作业

分析:设f[i]为1~i组成的数,可以得到f[i] = f[i-1] * 10^k + i.对于一个序列求第n项,一般可以用矩阵乘法来加速,但是每一个矩阵只能对应一个不变的递推式,这个式子中的k会变,那怎么办呢?那么在1~9,10~99,100~999每一次构造一个矩阵就好了,具体的矩阵如下: f(i + 1)       f(i)  10^k,1,1 i        =     i - 1    *    0, 1, 1 1   1 0, 0, 1 #include <cstdio> #i

bzoj2326:[HNOI2011]数学作业(分段矩阵乘法)

题目大意:输入n(n<=10^18)和m,将1~n的整数连起来模m输出,比如n=13则输出12345678910111213模m的数. 设f[i]为1~i整数连起来模m的数,i的位数为k,则有f[i]=(f[i-1]*10^k+i)mod m.可以发现f[i-1]和10^k都是会变化的,不能直接矩乘,这就尴尬了>_<.但是仔细想想(跑去问CZL),其实可以分段来矩乘,把k一样的数矩乘(1..9一样,10..99一样,100..999一样)就行了. orz CZL初二的时候1A,然而我却W

【矩阵乘法】bzoj2326 [HNOI2011]数学作业

http://hzwer.com/2831.html #include<cstdio> #include<iostream> #include<vector> using namespace std; typedef long long ll; typedef vector<ll> vec; typedef vector<vec> mat; ll n,MOD; mat operator * (const mat &a,const mat

【BZOJ2326】[HNOI2011]数学作业 矩阵乘法

[BZOJ2326][HNOI2011]数学作业 题解:对于位数相同的数字,这显然是满足矩乘性质的. 那么我们枚举每一位,如果当前i=10^k,那么维护行向量(sum,now,1),now代表当前的数,每次将sum*=i再加上now,now+=1即可. #include <cstdio> #include <cstring> #include <iostream> using namespace std; typedef long long ll; ll n,P; st

矩阵乘法专题4——bzoj 2326 [HNOI2011] 数学作业 题解

转载请注明:http://blog.csdn.net/jiangshibiao/article/details/24963747 [原题] 2326: [HNOI2011]数学作业 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 853  Solved: 473 [Submit][Status] Description [分析]我们按数字的位数来划分.对于K位数,我们就可以专门设计一个矩阵来计算. 然后就是注意细节了. [代码] #include

2326: [HNOI2011]数学作业

2326: [HNOI2011]数学作业 Description 不说什么ACTY了.. 题解: 线性的递推很容易写出来,f[i]=f[i-1]*10+i  (mod) 但是n很大,就需要用到矩阵乘法了.. 我们够造矩阵 10^i   0       0       f[i-1]        f[i] 1        1       0   *   i-1     =    i 1        1       1        1             1 #include<stdio.

【BZOJ 2326】 [HNOI2011]数学作业

2326: [HNOI2011]数学作业 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 1100  Solved: 625 [Submit][Status] Description 矩阵乘法. 可以用类似于秦九韶算法,把被取模的数拆开. 如123%m=(((1%m)*10+2)%m*10+3)%m 我们发现对于位数相同的数的计算方法是一样的,想到矩阵乘法. 对于1位的数: matrix x=10^1  0  0 1       1  0 0  

洛谷P3216 [HNOI2011]数学作业

洛谷P3216 [HNOI2011]数学作业 题目描述 小 C 数学成绩优异,于是老师给小 C 留了一道非常难的数学作业题: 给定正整数 N 和 M,要求计算 Concatenate (1 .. N) Mod M 的值,其中 Concatenate (1 ..N)是将所有正整数 1, 2, -, N 顺序连接起来得到的数.例如,N = 13, Concatenate (1 .. N)=12345678910111213.小C 想了大半天终于意识到这是一道不可能手算出来的题目,于是他只好向你求助,

[HNOI2011]数学作业

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