BZOJ3277:串 后缀自动机+离线处理+树状数组(&&BZOJ3473)
3544:[ONTAK2010]Creative Accounting 贪心+迷の卡常数

BZOJ3866:The Romantic Hero dp

shinbokuow posted @ Jan 14, 2015 09:45:40 PM in BZOJ with tags DP , 913 阅读

思路:

令\(f[i][j]\)表示最后一个数的位置\(\leq{i}\),异或起来等于\(j\)的序列数,\(g[i][j]\)表示第一个数的位置\(\geq{i}\),与起来等于\(j\)序列数.

我们差分之后就很容易得到结尾、开头位置确定的异或、与的序列个数了.

这两个东西知道之后,随便维护个前缀和什么的就行了.

(大常数\(O(n^2)\),目前倒数第一)

#include<cstdio>
#include<cstring>
#include<cctype>
#include<climits>
#include<iostream>
#include<algorithm>
using namespace std;
  
#define N 1010
#define M 1024
int f[N][M],g[N][M],a[N],add[M][N];
  
static const int mod=(1e9)+7;
  
inline void inc(int&x,int y){if((x+=y)>=mod)x-=mod;}
inline int dec(int x,int y){return (x-y+mod)%mod;}
int main(){
    int T;scanf("%d",&T);
    register int i,j;int n;
    while(T--){
        scanf("%d",&n);for(i=1;i<=n;++i)scanf("%d",&a[i]);
        for(memset(f,0,sizeof f),i=1;i<=n;++i){
            inc(f[i][a[i]],1);
            for(j=0;j<M;++j)inc(f[i][a[i]^j],f[i-1][j]);
            for(j=0;j<M;++j)inc(f[i][j],f[i-1][j]);
        }
        for(memset(g,0,sizeof g),i=n;i>=1;--i){
            inc(g[i][a[i]],1);
            for(j=0;j<M;++j)inc(g[i][a[i]&j],g[i+1][j]);
            for(j=0;j<M;++j)inc(g[i][j],g[i+1][j]);
        }
          
        for(i=n;i>=1;--i)for(j=0;j<M;++j)f[i][j]=dec(f[i][j],f[i-1][j]);
        for(i=1;i<=n;++i)for(j=0;j<M;++j)g[i][j]=dec(g[i][j],g[i+1][j]);
          
        for(j=0;j<M;++j)for(i=n;i>=1;--i)add[j][i]=add[j][i+1],inc(add[j][i],g[i][j]);
          
        int ans=0;
        for(j=0;j<M;++j)for(i=1;i<=n;++i)inc(ans,(long long)f[i][j]*add[j][i+1]%mod);
          
        printf("%d\n",ans);
    }
      
    return 0;
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter