分析:有大佬说可以用线性基写,可惜我不会,这是用DP写的
题目明确说明可到达的位置只与能值有关,和下标无关,我们就可以排个序,这样每个数可以转移的区间就是它的所有后缀
我们可以用dp[i][j]表示到达第i个位置,当前耐久度为j是否可行,那就可以根据走或不走两种情况来安排状态转移
也就是说能判断dp[i]j]能不能到达得看存不存在dp[i-1][j]或者dp[i-1][j^a[i].val](注意,两次异或同一数等于没有异或)
另外,排序会存在相等情况,但是题目说过只能到能级比它小的,所以得特判相等的情况
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int inf=1<<30; 4 typedef long long ll; 5 const double pi=acos(-1); 6 const int mod=2000120420010122; 7 const int maxn=3010; 8 bool dp[maxn][10000];//注意第二维不能够只开到3000 9 struct node{ 10 int id,val; 11 }a[3010]; 12 bool cmp(const node& a,const node& b){ 13 return a.val>b.val; 14 } 15 int main(){ 16 int n;scanf("%d",&n); 17 for(int i=0;i<n;i++)scanf("%d",&a[i].val),a[i].id=i; 18 sort(a,a+n,cmp); 19 for(int i=0,flag=1;i<n;i++){ 20 if(a[i].id==0){ 21 flag=0; 22 dp[i][a[i].val]=1; 23 continue; 24 } 25 if(flag) continue; 26 if(a[i].id==n-1){ 27 for(int j=10000;j>0;j--){ 28 dp[i][j]=dp[i-1][j^a[i].val]; 29 if(dp[i][j]){ 30 cout<<j<<endl; 31 return 0; 32 } 33 } 34 } 35 if(a[i].val==a[i-1].val){ 36 for(int j=10000;j>0;j--){ 37 dp[i][j]=dp[i-1][j]; 38 } 39 } 40 else { 41 for(int j=10000;j>0;j--){ 42 dp[i][j]=dp[i-1][j]|dp[i-1][j^a[i].val]; 43 } 44 } 45 } 46 cout<<"-1 "; 47 return 0; 48 }