2326: [HNOI2011]数学作业

来源:互联网 发布:数据结构与算法分析c 编辑:程序博客网 时间:2024/04/29 11:18

2326: [HNOI2011]数学作业

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 1751  Solved: 1038
[Submit][Status][Discuss]

Description

Input

Output

Sample Input

Sample Output

HINT

Source

[Submit][Status][Discuss]

令f[i]为Concatenate(i)%M
d[i]为10^i的位数
f[i] = f[i-1]*d[i] + i
这个式子分18次矩阵乘法即可

注意特判N%10 == 0
中间结果注意long long以及。。。。long long会被乘爆的,日
#include<iostream>#include<cstdio>#include<queue>#include<vector>#include<bitset>#include<algorithm>#include<cstring>#include<map>#include<stack>#include<set>#include<cmath>#include<ext/pb_ds/priority_queue.hpp>using namespace std;typedef long long LL;LL N,M,Ans[3],Nex[3];struct R{LL a[3][3];R(){memset(a,0,sizeof(a));}R operator * (const R &b) {R c;for (int i = 0; i < 3; i++)for (int j = 0; j < 3; j++)for (int l = 0; l < 3; l++)c.a[i][j] += a[i][l]*b.a[l][j]%M,c.a[i][j] %= M;return c;}}K;void Cal(){memset(Nex,0,sizeof(Nex));for (int i = 0; i < 3; i++)for (int j = 0; j < 3; j++)Nex[i] += Ans[j]*K.a[j][i]%M,Nex[i] %= M;for (int i = 0; i < 3; i++) Ans[i] = Nex[i];}R ksm(R now,LL y){R ret;for (int i = 0; i < 3; i++) ret.a[i][i] = 1;for (; y; y >>= 1LL) {if (y&1LL) ret = ret*now;now = now*now;}return ret;}int main(){#ifdef DMCfreopen("DMC.txt","r",stdin);#endifcin >> N >> M;LL i = 10; Ans[1] = Ans[2] = 1;for (; i < N; i *= 10LL) {K.a[0][0] = i%M; K.a[0][1] = 0; K.a[0][2] = 0;K.a[1][0] = 1; K.a[1][1] = 1; K.a[1][2] = 0;K.a[2][0] = 0; K.a[2][1] = 1; K.a[2][2] = 1;K = ksm(K,i - i/10LL);Cal();}if (N % 10 != 0) {K.a[0][0] = i%M; K.a[0][1] = 0; K.a[0][2] = 0;K.a[1][0] = 1; K.a[1][1] = 1; K.a[1][2] = 0;K.a[2][0] = 0; K.a[2][1] = 1; K.a[2][2] = 1;K = ksm(K,N - i/10LL + 1LL);Cal();}else {K.a[0][0] = i%M; K.a[0][1] = 0; K.a[0][2] = 0;K.a[1][0] = 1; K.a[1][1] = 1; K.a[1][2] = 0;K.a[2][0] = 0; K.a[2][1] = 1; K.a[2][2] = 1;K = ksm(K,N - i/10LL);Cal();i %= M; i *= 10LL;K.a[0][0] = i%M; K.a[0][1] = 0; K.a[0][2] = 0;K.a[1][0] = 1; K.a[1][1] = 1; K.a[1][2] = 0;K.a[2][0] = 0; K.a[2][1] = 1; K.a[2][2] = 1;Cal();}cout << Ans[0];return 0;}

0 0