标签:beep pdu vtk not upx span mmc neu gil
矩阵快速幂
是可以自己新定义运算的,
只要满足结合律即可
最近心血来潮,
搞出了一个叫
"矩阵max法"的东西(我瞎编的名字)
以下是运算规则
\(C=A \: \; max \; B \\C_{i,j}=MAX^n_{k=1}\left\{ A_{i,k}+B_{k,j}\right\}\)
关于结合律的证明
令
\(D=B\;max\;C \\ E=A \;max\; D=A \;max\;(B\;max\;C)\)
则
\(\begin{eqnarray} E_{i,j} &=&Max^n_{k=1}\left\{A_{i,k}+D_{k,j}\right\}\\ &=&Max^n_{k=1}\left\{A_{i,k}+MAX^n_{l=1}\left\{B_{k,l}+C_{l,j}\right\}\right\}\\ &=&Max^n_{k=1}\left\{MAX^n_{l=1}\left\{A_{i,k}+B_{k,l}+C_{l,j}\right\}\right\}\\ &=&Max^n_{k=1}\left\{MAX^n_{l=1}\left\{A_{i,k}+B_{k,l}\right\}+C_{l,j}\right\} \end{eqnarray}\)
即
\(E=A\;max\;B\;max\;C=A \;max\;(B\;max\;C)\)
其中max法单位矩阵如下
\(I=\begin{bmatrix}0 & -inf&-inf &...&-inf \\ -inf & 0&-inf&...&-inf\\ \vdots & &\ddots &&\vdots \\ -inf&-inf&\cdots&0&-inf\\ -inf&-inf&\cdots&-inf&0 \end{bmatrix} \quad\)
零矩阵就更加简单了
\(O=\begin{bmatrix}-inf & -inf&-inf &...&-inf \\ -inf & -inf&-inf&...&-inf\\ \vdots & &\ddots &&\vdots \\ -inf&-inf&\cdots&-inf&-inf\\ -inf&-inf&\cdots&-inf&-inf \end{bmatrix} \quad\)
有了这些,我们就可以快速幂了
#include<cstdio>
#include<cstring>
using namespace std;
int maxa=0;
int a[1000010],b[1000010];
long long ans[110][110],f[110];
long long stm[110][110],dt[110][110];
inline long long max(long long x,long long y){return (x>y?x:y);}
void DB()
{
int i,j,k;
for(i=1;i<=maxa;i++)
{
for(j=1;j<=maxa;j++)
{
printf("%d,%d\n",i,j);
for(k=1;k<=maxa;k++) printf("%lld ",ans[i][k]+ans[k][j]);
printf("\n");
// printf("%d ",ans[i][j]);
}
printf("\n");
}
printf("\n");
}
void sqr()
{
int i,j,k;
memset(dt,250,sizeof(dt));
for(i=1;i<=maxa;i++)
for(j=1;j<=maxa;j++)
for(k=1;k<=maxa;k++) dt[i][j]=max(dt[i][j],ans[i][k]+ans[k][j]);
// DB();
for(i=1;i<=maxa;i++)
for(j=1;j<=maxa;j++) ans[i][j]=dt[i][j];
}
void mul()
{
int i,j,k;
memset(dt,250,sizeof(dt));
for(i=1;i<=maxa;i++)
for(j=1;j<=maxa;j++)
for(k=1;k<=maxa;k++) dt[i][j]=max(dt[i][j],ans[i][k]+stm[k][j]);
for(i=1;i<=maxa;i++)
for(j=1;j<=maxa;j++) ans[i][j]=dt[i][j];
}
void qpow(long long x)
{
int i;
memset(ans,200,sizeof(ans));
for(i=1;i<=maxa;i++) ans[i][i]=0;
// for(i=1;i<=maxa;i++) ans[i][maxa]=f[i];
for(i=0;(x>>i)>0;i++);i--;
for(;i>=0;i--)
{
sqr();
if((x>>i)&1) mul();
}
}
int main()
{
freopen("backpack.in","r",stdin);
freopen("backpack.out","w",stdout);
int n,i,j;long long m;
scanf("%d%lld",&n,&m);
for(i=1;i<=n;i++) scanf("%d%d\n",&a[i],&b[i]);
for(i=1;i<=n;i++) if(maxa<a[i]+1) maxa=a[i]+1;
// maxa++;
memset(f,0,sizeof(f));
for(i=1;i<=n;i++)
for(j=a[i];j<=maxa;j++) f[j]=max(f[j],f[j-a[i]]+b[i]);
memset(stm,250,sizeof(stm));
for(i=2;i<=maxa;i++) stm[i][i-1]=0;
for(i=1;i<=n;i++) stm[maxa-a[i]+1][maxa]=max(stm[maxa-a[i]+1][maxa],b[i]);
if(m<maxa){printf("%d\n",f[m]);return 0;}
qpow(m-maxa+1);
/* for(i=1;i<=15;i++) printf("%lld\n",f[i]);
for(i=1;i<=maxa;i++)
{
for(j=1;j<=maxa;j++)
if(ans[i][j]>=0) printf("%3lld ",ans[i][j]);
else printf("inf ");
printf("\n");
}*/
long long outans=-9223372036854775807ll;
for(i=2;i<=maxa;i++) outans=max(outans,f[i-1]+ans[i][maxa]);
printf("%lld\n",outans);
return 0;
}
矩阵快速幂——max JZOJ(GMOJ)6309 完全背包
标签:beep pdu vtk not upx span mmc neu gil
原文地址:https://www.cnblogs.com/JY-Chen/p/11378862.html