正解:矩阵快速幂
解题报告:
一看到这个就应该能想到矩阵快速幂?
然后就考虑转移式,发现好像直接想不好想,,,主要的问题在于这个*$i$,就很不好搞$QAQ$
其实不难想到,$\sum_{i=1}^{n}a_i\cdot(n-i)$这样一个式子是可以在矩阵快速幂中推出来的(类似这个形式的都可,,,就随着编号递增系数递减这样子$QwQ$
具体来说就是表示成$\sum_{i=1}^{n}\sum_{j=1}^{i}a_j$,就欧克辣(具体实现后面港,,,
但是问题在于,它是$\sum_{i=1}^{n}a_i\cdot i$这样的,就随着编号递增系数递增这样子的$QwQ$
那显然就想到,变形嘛,就变成$\sum_{i=1}^{n}a_i\cdot n-\sum_{i=1}^{n}a_i\cdot(n-i)$这样子
然后就做完辣,,,?
剩下的就是考虑怎么表示出$\sum_{i=1}^{n}a_i$和$\sum_{i=1}^{n}a_i\cdot(n-i)$辣
对于第一个的话,可以考虑$\begin{bmatrix}\sum_{j=1}^{i-1} f_i \\ f_i\\ f_{i-1}\end{bmatrix}$$\cdot$$\begin{bmatrix}1 & 1 & 0\\ 0 & 1 & 1\\ 0 & 1 & 0\end{bmatrix}$,就欧克辣
然后第二个就差不多的方法,再加一维就好,$\begin{bmatrix}\sum _{j=1}^{i-1}\sum_{k=1}^{j}f_k\\ \sum_{j=1}^{i}f_j\\ f_{i+1}\\ f_{i}\end{bmatrix}$$\cdot$$\begin{bmatrix}1 & 1 & 0 & 0\\ 0 & 1 & 1 & 0\\ 0 & 0 & 1 & 1\\0 & 0 & 1 & 0\end{bmatrix}$
欧克做完辣,,,
#include<bits/stdc++.h> using namespace std; #define il inline #define int long long #define gc getchar() #define ri register int #define rb register bool #define rc register char #define rp(i,x,y) for(ri i=x;i<=y;++i) int n,mod; struct matrix{int mat[5][5];il void clr(){memset(mat,0,sizeof(mat));}}e1,e2,fib; il int read() { rc ch=gc;ri x=0;rb y=1; while(ch!=‘-‘ && (ch>‘9‘ || ch<‘0‘))ch=gc; if(ch==‘-‘)ch=gc,y=0; while(ch>=‘0‘ && ch<=‘9‘)x=(x<<1)+(x<<3)+(ch^‘0‘),ch=gc; return y?x:-x; } il matrix multi(matrix gd,matrix gs) { matrix ret;ret.clr(); rp(i,0,3) rp(j,0,3) rp(k,0,3)ret.mat[i][j]=(ret.mat[i][j]+gd.mat[i][k]*gs.mat[k][j]%mod)%mod; return ret; } il matrix power_1(ri x) {matrix ret;ret.clr();ret.mat[0][1]=1;while(x){if(x&1)ret=multi(ret,e1);e1=multi(e1,e1);x>>=1;}return ret;} il matrix power_2(ri x) {matrix ret;ret.clr();ret.mat[0][2]=1;while(x){if(x&1)ret=multi(ret,e2);e2=multi(e2,e2);x>>=1;}return ret;} namespace sub1 { il void main() { int fib1=1,fib2=1,as=0; rp(i,1,n){as=(as+1ll*fib1*i%mod)%mod;fib2+=fib1;fib1=fib2-fib1;if(fib2>=mod)fib2-=mod;} printf("%lld\n",as); } } main() { // freopen("fib.in","r",stdin);freopen("fib.out","w",stdout); n=read();mod=read(); // if(n<=100)return sub1::main(),0; e1.clr();e1.mat[0][0]=1;e1.mat[1][0]=1;e1.mat[1][1]=1;e1.mat[2][1]=1;e1.mat[1][2]=1; e2.clr();e2.mat[0][0]=1;e2.mat[1][0]=1;e2.mat[1][1]=1;e2.mat[2][1]=1;e2.mat[2][2]=1;e2.mat[3][2]=1;e2.mat[2][3]=1; matrix as1=power_1(n),as2=power_2(n); printf("%lld\n",((as1.mat[0][0]*n%mod-as2.mat[0][0])%mod+mod)%mod); return 0; }
最后放下代码就好辣!(跑得飞慢,,,QAQ
原文地址:https://www.cnblogs.com/lqsukida/p/10805186.html