HNOI2011 数学作业
这个题……多么希望他是可以\(O(n)\)做的呀……取模练习题
考虑一下用\(f[i]\)表示到第i个数的结果,很容易得到:\(f[i] = f[i-1] * 10^k + i\)。其中k是当前数的位数。
这个显然可以用矩乘优化……不过因为k是变量,所以麻烦一点……不过不要紧,对于不同位数的数我们分开做就好了。
然后好像我的写法兼容性还不错……不是特别需要考虑什么10的指数幂之类的特例。不过我还是调了好久……因为我忘了矩乘不满足交换律……
看一下代码。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<cstring>
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar('\n')
#define pr pair<int,int>
#define mp make_pair
#define fi first
#define sc second
#define fr friend inline
using namespace std;
typedef long long ll;
const int M = 100005;
const int N = 10000005;
ll read()
{
ll ans = 0,op = 1;
char ch = getchar();
while(ch < '0' || ch > '9')
{
if(ch == '-') op = -1;
ch = getchar();
}
while(ch >='0' && ch <= '9')
{
ans *= 10;
ans += ch - '0';
ch = getchar();
}
return ans * op;
}
ll n,m,cur = 1;
struct matrix
{
ll f[4][4];
matrix(){memset(f,0,sizeof(f));}
fr matrix operator * (const matrix &a,const matrix &b)
{
matrix c;
rep(i,0,2)
rep(j,0,2)
rep(k,0,2)
c.f[i][j] += a.f[i][k] * b.f[k][j],c.f[i][j] %= m;
return c;
}
fr matrix operator ^ (matrix a,ll b)
{
matrix c;
rep(i,0,2) c.f[i][i] = 1;
while(b)
{
if(b & 1) c = c * a;
a = a * a,b >>= 1;
}
return c;
}
}F,D,E;
int main()
{
F.f[0][1] = 1,F.f[1][1] = 1,F.f[1][2] = 1,F.f[2][2] = 1;
D.f[1][0] = D.f[2][0] = 1;
n = read(),m = read();
while(n >= pow(10,cur))
{
F.f[0][0] = (ll)pow(10,cur) % m;
D = (F ^ (ll)(pow(10,cur) - (ll)pow(10,cur-1))) * D;
cur++;
}
n -= (ll)pow(10,cur-1);
F.f[0][0] = (ll)pow(10,cur) % m;
F = F ^ (n+1),D = F * D;
printf("%lld\n",D.f[0][0]);
return 0;
}
当你意识到,每个上一秒都成为永恒。