BZOJ2326 [HNOI2011]数学作业(分块矩阵快速幂)
题意:
定义函数Concatenate (1 ..N)是将所有正整数 1, 2, …, N 顺序连接起来得到的数,如concatenate(1..5)是12345,求concatenate(1...n)%m的值
思路:
矩阵快速幂,公式为
$$
\left[
\begin{matrix}
f(n)\\n\\1
\end{matrix}
\right]=
\left[
\begin{matrix}
10^k&1&1\\
0&1&1\\
0&0&1
\end{matrix}
\right]
\left[
\begin{matrix}
f(n-1)\\n-1\\1
\end{matrix}
\right]
$$
其中$10^k$可以分快处理,分n为0~9,10~99,100~999等
代码:
/************************************************************** Problem: 2326 User: wrjlinkkkkkk Language: C++ Result: Accepted Time:64 ms Memory:1292 kb ****************************************************************/ #include<iostream> #include<iomanip> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<string> #include<stack> #include<queue> #include<deque> #include<set> #include<vector> #include<map> #include<functional> #include<list> #define fst first #define sc second #define pb push_back #define mp(a,b) make_pair(a,b) #define mem(a,b) memset(a,b,sizeof(a)) #define lson l,mid,root<<1 #define rson mid+1,r,root<<1|1 #define lc root<<1 #define rc root<<1|1 #define lowbit(x) ((x)&(-x)) #pragma Gcc optimize(2) using namespace std; typedef double db; typedef long double ldb; typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> PI; typedef pair<ll,ll> PLL; const int maxn = 10000 + 100; const int maxm = 5e3 + 100; const double eps = 1e-10; const int inf = 0x3f3f3f3f; const double pi = acos(-1.0); int scan(){ int res=0,ch,flag=0; if((ch=getchar())=='-') flag=1; else if(ch>='0'&&ch<='9') res=ch-'0'; while((ch=getchar())>='0'&&ch<='9') res=res*10+ch-'0'; return flag?-res:res; } ll n, m; ll mul(ll x,ll y){ ll s=0; while(y) { if(y&1)s=(s+x)%m; x=(x<<1)%m; y>>=1; } return s; } void mtpl(ll a[4][4], ll b[4][4],ll s[4][4]){ ll tmp[4][4]; for(int i = 1; i <= 3; i++){ for(int j = 1; j <= 3; j++){ tmp[i][j]=0; for(int k = 1; k <= 3; k++){ tmp[i][j] += mul(a[i][k] , b[k][j])%m; } } } for(int i = 1; i <= 3; i++){ for(int j = 1; j <= 3; j++){ s[i][j] = tmp[i][j]; } } return; } ll b[4][4]; void Fast_power(ll t,ll last){ ll a[4][4]; mem(a, 0); a[1][1] = t; a[2][1] = a[3][1] = a[2][2] = a[3][2] = a[3][3] = 1; ll y = last-t/10+1; while(y){ if(y & 1) mtpl(b, a, b); mtpl(a, a, a); y >>= 1; } //prt(ans); return; } int main(){ scanf("%lld %lld", &n, &m); mem(b, 0); for(int i = 1; i <= 3; i++)b[i][i] = 1; ll t = 10; while(t <= n){ Fast_power(t, t-1); t*=10; } Fast_power(t,n); printf("%lld", b[3][1]%m); return 0; } /* 8 3287492749272074 */