码迷,mamicode.com
首页 > 其他好文 > 详细

矩阵快速幂——max JZOJ(GMOJ)6309 完全背包

时间:2019-08-19 19:20:42      阅读:95      评论:0      收藏:0      [点我收藏+]

标签:beep   pdu   vtk   not   upx   span   mmc   neu   gil   

矩阵快速幂——max JZOJ(GMOJ)6309 完全背包



技术图片

前置知识

矩阵快速幂
是可以自己新定义运算的,
只要满足结合律即可
最近心血来潮,
搞出了一个叫
"矩阵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\)

有了这些,我们就可以快速幂了

代码(我快速幂打的丑,不要乱Copy)

#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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!