Parity of Tuples (Easy)(贡献+状压dp)

Parity of Tuples (Easy)

题意:

输入 n ( 1 e 4 ) , m ( 10 ) , k ( 30 ) n(1e4),m(10),k(30) n(1e4),m(10),k(30)
接下来 n n n行,第 i i i行输入 a i 1 , a i 2 , … , a i m ( 0 ≤ a i j < 2 k ) a_{i1},a_{i2},\dots,a_{im}(0\leq a_{ij}<2^k) ai1,ai2,,aim(0aij<2k)
∑ x = 0 2 k − 1 c o u n t ( x ) 3 x m o d    1 0 9 + 7 \sum_{x=0}^{2^k-1}count(x)3^x\mod10^9+7 x=02k1count(x)3xmod109+7
其中 c o u n t ( x ) count(x) count(x)表示 i i i的个数,对于任意的 1 ≤ j ≤ m 1\leq j\leq m 1jm使 a i j & x a_{ij}\&x aij&x中位为1的个数为奇数。

题解:

显然可以分析出,不同的 i i i,(即不同的行),它的贡献是相互独立的。于是便对每一行算贡献。
而对于每一行,肯定要从位的角度考虑问题,于是就引入状压 d p dp dp
d p [ i ] [ j ] dp[i][j] dp[i][j]表示 0 , 1 , … , i − 1 0,1,\dots,i-1 0,1,,i1位,状态为 j j j(位为1表示奇数),的贡献。
转移:
d p [ i ] [ j ] = d p [ i ] [ j ] + d p [ i − 1 ] [ j ] dp[i][j]=dp[i][j]+dp[i-1][j] dp[i][j]=dp[i][j]+dp[i1][j]不算该位贡献;
d p [ i ] [ j ] = d p [ i ] [ j ] + d p [ i − 1 ] [ j ⨁ s t ] × 3 2 i − 1 dp[i][j]=dp[i][j]+dp[i-1][j\bigoplus st]\times3^{2^{i-1}} dp[i][j]=dp[i][j]+dp[i1][jst]×32i1算该位的贡献。
最后返回 d p [ k ] [ 2 m − 1 ] dp[k][2^m-1] dp[k][2m1]

代码:

#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
int n,m,k,a[19];
int dp[34][1<<11];
int base[39];
int solve(){
    for(int i=1;i<=m;i++)cin>>a[i];
    for(int i=0;i<=k;i++)for(int j=0;j<(1<<m);j++)dp[i][j]=0;
    dp[0][0]=1;
    for(int i=1;i<=k;i++){
        int zt=0;
        for(int j=1;j<=m;j++)if(a[j]&(1<<(i-1)))zt|=(1<<j-1);
        for(int j=0;j<(1<<m);j++){
            dp[i][j]=(dp[i][j]+dp[i-1][j])%mod;
            dp[i][j]=(dp[i][j]+1ll*dp[i-1][j^zt]*base[i-1])%mod;
        }
    }
    return dp[k][(1<<m)-1];
}
int main(){
    //freopen("tt.in","r",stdin),freopen("tt.out","w",stdout);
    base[0]=3;
    for(int i=1;i<=31;i++)base[i]=1ll*base[i-1]*base[i-1]%mod;
    while(cin>>n>>m>>k){
        int ans=0;
        while(n--)ans=(ans+solve())%mod;
        cout<<ans<<endl;
    }
    return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值