题意:给定n,k,l,接下来给出n个数,让你从n个数中选取k个数围成一圈,然后从这k个数中随意选出连续的m(m>=1&&m<=k)个数进行异或后得到[l,r]区间的所有值,让你求最大的r。
分析:关键问题是需要剪枝!
代码实现:
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<string> #include<set> #include<vector> using namespace std; int n,k,L,R,a[25],b[10],id; int visited[130]; string str[10] = {"1", "12", "123", "1234", "12345", "123456"}; int check() { int i,j,temp[1005],tot=0,t; temp[tot++]=0; for(i=0;i<k;i++)//枚举所有的组合异或值 { t=tot; for(j=0;j<tot;j++) temp[t++]=b[i]^temp[j]; tot=t; } for(i=0;i<tot;i++) visited[temp[i]]=id; for(i=L;i<=R;i++) if(visited[i]!=id) return 0; return 1; } void dfs(int x, int num) { int i,j; if(num==k) { id++; if(check()==0) return ; string per = str[k-1]; do { if(per[0]!='1')//这里去除了很多重复的,没加这句话500ms,加了之后100ms break; id++; int temp[12]; for(i=0;i<k;i++) { temp[i]=b[per[i]-'0'-1]; temp[i+k]=temp[i]; } for(i=0;i<k;i++) { int flag=0; for(j=i;j<i+k;j++) { flag=flag^temp[j]; visited[flag]=id; } } if(visited[L]!=id) continue; i=L+1; while(visited[i]==id) i++; R=R>(i-1)?R:(i-1); } while(next_permutation(per.begin(),per.end())); return ; } for(i=x;i<n;i++) { b[num]=a[i]; dfs(i+1,num+1); } } int main() { int i; while(scanf("%d%d%d",&n,&k,&L)!=EOF) { id=0;R=0; memset(visited,-1,sizeof(visited)); for(i=0; i<n; i++) scanf("%d",&a[i]); dfs(0,0); printf("%d ",R); } return 0; }