题意:有N盏灯和M个开关,每一个开关控制多盏灯(比如N=4,"1010"就代表这个开关控制第1和第3盏灯),初始所有的灯都是开着的。问你有多少种按开关的方法使得所有的灯都熄灭?(只能选择一段连续的开关区间,区间长度在[a,b]范围内。)
思路:
先知道前缀异或和sum,这个sum[i]保存开关[1~i]的异或和,那个开关区间[l,R]能产生的作用就是sum[R]^sum[L].
用map<string,int>保存前缀和为string时的个数,比如sum[5]=1010,sum[8]=1010,map["1010"]=2;
枚举每一个开关,ans+=这个开关所在的区间的解决方法有多少种
注意一个小技巧,map动态更新,就不需要一开始存那么多
代码:
#include<map>
#include<string>
#include<cstdio>
typedef long long LL;
using namespace std;
const int MAXN = 300005;
char get[55];//目标态
string sum[MAXN];
map<string,int>maps;//前缀异或string,对应的个数
int n,m,a,b,cas,ans;
string XOR(string a,string b)//返回a异或b的字符串
{
string c="";
for(int j=0;j<n;j++)
c+=(a[j]-'0')^(b[j]-'0')+'0';
return c;
}
void solve()
{
for(int i=1;i<=m;i++){
char s[55]={0};
scanf("%s",s);
sum[i]=XOR(sum[i-1],s); //计算[1~i]的前缀异或和
if(i>=a) maps[sum[i-a]]++; //在规定长度内就进maps
if(i>b)maps[sum[i-b-1]]--; //不在规定长度就出maps
if(i>=a)ans+=maps[XOR(sum[i],get)]; //累加能到达目标的方法数
}
printf("Case %d: %d\n",++cas,ans);
}
int main()
{
while(~scanf("%d%d%d%d",&n,&m,&a,&b)){
sum[0]="";
for(int i=0;i<n;i++) {get[i]='1';sum[0]+='0';}
maps.clear(); ans=0;
//以上初始化
solve();
}
return 0;
}
题目描述
You are a fan of "Internet of Things"(IoT, 物联网), so you build a nice Internet of Lights and Switches in your huge mansion. Formally, there are n lights and m switches, each switch controls one or more lights, i.e. pressing that switch flips the status of those lights (on->off, off->on).
Initially, all the lights are on. Your task is to count the number of ways to turn off all the lights by pressing some consecutive switches. Each switch should not be pressed more than once. There is only one restriction: the number of switches you pressed should be between a and b (inclusive).
输入描述
There will be at most 20 test cases. Each test case begins with a line containing four integers n, m, a, b (2<=n<=50, 1<=a<=b<=m<=300000). Each of the following m lines contains a 01 string of length n. The i-th character is 1 if and only if that switch controls the i-th light. The size of the whole input file does not exceed 8MB.