列表

详情


NC20222. [JSOI2016]位运算

描述

JYY最近在研究位运算。他发现位运算中最有趣的就是异或(xor)运算。对于两个数的异或运算,JYY发现了一个结论:两个数的异或值为0当且仅当他们相等。于是JYY又开始思考,对于N个数的异或值会有什么性质呢?
【问题描述】
JYY想知道,如果在0到R-1的范围内,选出N个不同的整数,并使得这N个整数的异或值为0,那么一共有多少种选择的方法呢?(选择的不同次序并不作重复统计,请参见样例)
JYY是一个计算机科学家,所以他脑海里的R非常非常大。为了能够方便的表达,如果我们将R写成一个0-1串,那么R是由一个较短的0-1串S重复K次得到的。
比如,若S=“101”,K=2,那么R的2进制表示则为“101101”。由于计算的结果会非常大,JYY只需要你告诉他选择的总数对10^9+7取模的结果即可

输入描述

第一行包含两个正整数N和K。
接下来一行包含一个由0和1组成的字符串S。
我们保证S的第一个字符一定为1。

输出描述

一行一个整数,表示选择的方案数对10^9+7取模的值。

示例1

输入:

3 1
100

输出:

1

说明:

对于第一个样例, 唯一的一种选择方法是选择 {1, 2, 3}。

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++11(clang++ 3.9) 解法, 执行用时: 481ms, 内存消耗: 1128K, 提交时间: 2019-03-16 12:57:37

#include<cstdio>
#include<cstring>
#include<algorithm>
#define mo 1000000007
using namespace std;
int n,k;
char s[1000];
struct mat{
    int m[130][130];
    mat(){
        for (int i=0;i<(1<<n);i++)
            for (int j=0;j<(1<<n);j++)
                m[i][j]=0;
    }
} a[2];
mat mul(mat a,mat b){
    mat re;
    for (int i=0;i<(1<<n);i++)
        for (int j=0;j<(1<<n);j++)
            for (int k=0;k<(1<<n);k++){
                re.m[i][j]+=1ll*a.m[i][k]*b.m[k][j]%mo;
                if (re.m[i][j]>=mo) re.m[i][j]-=mo;
            }
    return re;
}
int main(){
    scanf("%d%d%s",&n,&k,&s);int len=strlen(s);
    
    for (int zt=0;zt<(1<<n);zt++){
        for (int zy=0;zy<(1<<n);zy++){
            int td=0;
            for (int i=1;i<=n;i++) if (zy&(1<<(i-1))) td++;
            if (td&1) continue;

            if (zt&1){
                int ha=0;
                for (int i=n;i;i--){
                    if (zy&(1<<(i-1))) ha=1;
                    if (zt&(1<<(i-1))) break;
                }
                if (ha) continue;
            }
            
            td=0;
            for (int i=1;i<n;i++) if ((zy&(1<<(i-1)))&&!(zy&(1<<i))){
                if (!(zt&(1<<i))) td=1;
            }
            if (td) continue;
    
            int go=zt;
            for (int i=1;i<n;i++) if (!(zy&(1<<(i-1)))&&(zy&(1<<i)))
                go|=(1<<i);
            a[0].m[go][zt]++;
        }
    }

    for (int zt=0;zt<(1<<n);zt++){
        for (int zy=0;zy<(1<<n);zy++){
            int td=0;
            for (int i=1;i<=n;i++) if (zy&(1<<(i-1))) td++;
            if (td&1) continue;

            int ha=0;
            for (int i=n;i;i--){
                if (zy&(1<<(i-1))) ha=1;
                if (zt&(1<<(i-1))) break;
            }
            
            td=0;
            for (int i=1;i<n;i++) if ((zy&(1<<(i-1)))&&!(zy&(1<<i))){
                if (!(zt&(1<<i))) td=1;
            }
            if (td) continue;
    
            int go=zt;
            for (int i=1;i<n;i++) if (!(zy&(1<<(i-1)))&&(zy&(1<<i)))
                go|=(1<<i);
            if (!ha&&(go&1)) go^=1;
            a[1].m[go][zt]++;
        }
    }
    
    mat td,ret,lj,init;
    for (int i=0;i<(1<<n);i++) td.m[i][i]=ret.m[i][i]=1;
    for (int i=0;i<len;i++) td=mul(a[s[i]-'0'],td);
    for (lj=td;k;k/=2,lj=mul(lj,lj)) if (k&1)
        ret=mul(ret,lj);
    init.m[1][0]=1;
    ret=mul(ret,init);
    printf("%d\n",ret.m[(1<<n)-2][0]);
}

C++14(g++5.4) 解法, 执行用时: 462ms, 内存消耗: 740K, 提交时间: 2020-06-09 14:23:42

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 7
#define S 50
#define X 1000000007
#define Inc(x,y) ((x+=(y))>=X&&(x-=X))
using namespace std;
int l,n,K,lim,op[1<<N],f[S+5][1<<N];char s[S+5];
struct M
{
	int a[1<<N][1<<N];I M() {memset(a,0,sizeof(a));}
	I int *operator [] (CI x) {return a[x];}
	I M operator * (Con M& o) Con
	{
		RI i,j,k;M t;for(i=0;i^lim;++i) for(j=0;j^lim;++j)
			for(k=0;k^lim;++k) t[i][j]=(1LL*a[i][k]*o.a[k][j]+t[i][j])%X;return t;
	}
	I M operator ^ (RI y) Con
	{
		M x=*this,t;for(RI i=0;i^lim;++i) t[i][i]=1;W(y) y&1&&(t=t*x,0),x=x*x,y>>=1;return t;
	}
}U;
I int T(CI p,CI k,CI s)
{
	RI i,x,y,t=0;for(i=n-1;i;--i) if(p>>i&1)
		{if((x=(k>>i)&1)>(y=(k>>i-1)&1)) return -1;x==y&&(t|=1<<i);}
	if(p&1) {if((x=k&1)>s) return -1;x==s&&(t|=1);}return t;
}
int main()
{
	RI i,j,k,t;scanf("%d%d%s",&n,&K,s+1),l=strlen(s+1);
	for(lim=1<<n,op[0]=i=1;i^lim;++i) op[i]=op[i>>1]^(i&1);
	for(RI w=0;w^lim;++w)
	{
		memset(f,0,sizeof(f)),f[0][w]=1;
		for(i=1;i<=l;++i) for(j=0;j^lim;++j) if(f[i-1][j])
			for(k=0;k^lim;++k) op[k]&&~(t=T(j,k,s[i]&1))&&Inc(f[i][t],f[i-1][j]);
		for(i=0;i^lim;++i) U[w][i]=f[l][i];
	}return printf("%d",(U^K)[lim-1][0]),0;
}

上一题