• 洛谷P3646 [APIO2015]巴厘岛的雕塑(数位dp)


    传送门

    话说莫非所有位运算都可以用贪心解决么……太珂怕啦……

    一直把或运算看成异或算我傻逼……

    考虑从高位到低位贪心,如果能使答案第$i$位为0那么肯定比不为$0$更优

    然后考虑第$i$位是否能为$0$

    设$f[i][j]$表示将前$i$个数分为$j$段,能否在最高位到第$i+1$位都与当前$ans$一致的情况下使第$i$位为0,可以的话$f[i][j]$为1,否则为0

    考虑状态如何转移

    如果$f[k][j-1]$为1且$sum[i]-sum[k]$的第$i$位为0则可以由$f[k][j-1]$转移到$f[i][j]$(其中$sum$表示前缀和)

    考虑如何判断,如果$f[k][j-1]==1$且

    (下面的$k$和上面那个$k$无关,因为变量有点多重复去了……)

    $((sum[i]-sum[k])>>k|ans)== ans$(最高位到倒数第k+1位是否与ans一致)

    $((S[i]-S[k])&1<<(k-1))==0$(倒数第k位能否为0)

    那么就可以转移了

    对于每个$x$,若$f[n][A~B]$有至少一个为1,$ans$的第$k$位就可以为0

    然后因为时间复杂度过不了最后一个子任务……所以$A=1$的时候特判一下……

    具体来说就是因为段数只有上限,所以把$f$数组的第二维省掉,就能降一个n

     1 //minamoto
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<cstring>
     5 #define ll long long
     6 #define inf 0x3f3f3f3f
     7 using namespace std;
     8 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
     9 char buf[1<<21],*p1=buf,*p2=buf;
    10 template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
    11 inline int read(){
    12     #define num ch-'0'
    13     char ch;bool flag=0;int res;
    14     while(!isdigit(ch=getc()))
    15     (ch=='-')&&(flag=true);
    16     for(res=num;isdigit(ch=getc());res=res*10+num);
    17     (flag)&&(res=-res);
    18     #undef num
    19     return res;
    20 }
    21 const int N=2005;
    22 ll sum[N];int f[105][105],g[N];
    23 ll ans=0,t;int n,l,r,len=0;
    24 void solve1(){
    25     int x,i,j;
    26     for(x=len;x;--x){
    27         for(i=1;i<=n;++i) g[i]=inf;
    28         for(i=1;i<=n;++i)
    29         for(j=0;j<i;++j)
    30         if(g[j]<r){
    31             t=sum[i]-sum[j];
    32             if((t>>(ll)x|ans)==ans&&(t&1ll<<(ll)x-1ll)==0) cmin(g[i],g[j]+1);
    33         }
    34         ans<<=1ll;
    35         if(g[n]>r) ++ans;
    36     }
    37 }
    38 void solve2(){
    39     int x,i,j,k;
    40     for(x=len;x;--x){
    41         memset(f,0,sizeof(f));
    42         f[0][0]=1;
    43         for(i=1;i<=n;++i)
    44         for(j=1;j<=i;++j)
    45         for(k=0;k<i;++k)
    46         if(f[k][j-1]){
    47             t=sum[i]-sum[k];
    48             if((t>>(ll)x|ans)==ans&&(t&1ll<<(ll)x-1ll)==0) f[i][j]=1;
    49         }
    50         for(i=l;i<=r;++i)
    51         if(f[n][i]) break;
    52         ans<<=1ll;
    53         if(i>r) ++ans;
    54     }
    55 }
    56 int main(){
    57 //    freopen("testdata.in","r",stdin);
    58     n=read(),l=read(),r=read();
    59     for(int i=1;i<=n;++i)
    60     sum[i]=sum[i-1]+read();
    61     for(t=sum[n];t;t>>=1) ++len;
    62     l==1?solve1():solve2();
    63     printf("%lld
    ",ans);
    64     return 0;
    65 }
  • 相关阅读:
    BizTalk2010简介
    各大类库的类工厂
    全国城市三级级联菜单(java+Ajax+jQuery)
    gcc编译系统
    通用排行榜组件
    本地化中文示例代码需求调查
    PortalBasic Java Web 应用开发框架(源码、示例及文档)
    FFLIB 框架
    ORM/IOC框架设计感悟
    个人日记
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9682703.html
Copyright © 2020-2023  润新知