//============================================================================ // Name : 博弈_序列中子序列异或值大于0.cpp // Author : cchun // Version : // Copyright : Your copyright notice // Description : Hello World in C++, Ansi-style //============================================================================ /* * state: Accepted 2060 KB 490 ms C++ (g++ 4.4.5) * 题目大意: * 给定一段序列,序列要用代码生成(这个纯粹是没有用的,不过有时候可能转机在这些东西也不一定)。然后 * 要求在这段序列上选择一个连续子序列,然后要求这个子序列Nim游戏,先手可胜利。 * 解题思路: * 把序列生成,然后序列变为a[i]^a[i+1]^a[i+2]^………^a[j] = dp[j]^dp[i-1], dp[i]为(a[0]^a[1]^a[2]^……^a[i]). * 然后就可以变为计数问题了。 * 如果序列为3,那么所有的序列的异或值为: * dp[0], dp[1], dp[2] * dp[1]^dp[0], dp[2]^dp[0] * dp[2]^dp[1] * 总共为3+2+1, 就是n*(n+1)/2种。排除其中为0的就行了。 * 就可以变为弄一个循环,然后再hash统计下后面有多少个跟它相同的。相同的就是不行,统计全部后用总值减去,就是解。 * 注意事项: * 那一步hash比赛时我为了求快用map,结果TLE了,比赛结束用hash表就ac了,490ms,花了1/5的时间。 * 理论时间复杂度,接近O(n),因为hash不是稳定的。比网络上那些需要排序的算法理论上快一些,因为 * 涉及到排序的算法,时间复杂度的下界为O(n*log(n)) */
View Code
1 #include <iostream> 2 #include <stdio.h> 3 #include <algorithm> 4 #include <functional> 5 #include <cmath> 6 #include <cstring> 7 #include <string> 8 #include <vector> 9 #include <map> 10 #include <set> 11 #include <utility> 12 #include <stack> 13 #include <queue> 14 #include <deque> 15 #include <bitset> 16 #include <iomanip> 17 #include <sstream> 18 19 #define abs(x) ((x)>0?(x):-(x)) 20 #define sqr(x) ((x)*(x)) 21 22 #define all(x) x.begin(), x.end() 23 #define rall(v) v.rbegin(),v.rend() 24 25 #define ll long long 26 #define ull unsigned long long 27 28 #define FOR(i,a,b) for(int i=(a); i<(b);i++) 29 #define FF(i,a) for(int i=0; i<(a);i++) 30 #define FFD(i,a) for(int i=(a)-1; i>=0;i--) 31 #define CC(m,what) memset(m,what,sizeof(m)) 32 #define SZ(a) ((int)a.size()) 33 #define viewPP(a,n,m) {puts("---");FF(i,n){FF(j,m) cout<<a[i][j] <<' ';puts("");}} 34 #define viewP(a, n) {FF(i, n) {cout<<a[i]<<" ";} puts("");} 35 36 #define read freopen("in.txt","r",stdin) 37 #define write freopen("out.txt","w",stdout) 38 39 const double eps = 1e-11; 40 const int inf = 0x7fffffff; 41 const int hinf = 0x3f3f3f3f; 42 const double pi = 3.1415926535897932; 43 44 int dx[] = {-1, 0, 1, 0};//up Right down Left 45 int dy[] = {0, 1, 0, -1}; 46 47 using namespace std; 48 const int maxn = 100005; 49 int S, W, N; 50 int a[maxn]; 51 int dp[maxn]; 52 53 54 class myHash { 55 public: 56 static const int MAXN = 139991; 57 static const int hinf = 0x3f3f3f3f; 58 int Hash[MAXN]; 59 int hashVal[MAXN]; 60 int k; 61 bool get_key(int x, int &ind) { 62 int k = ((x % MAXN) + MAXN) % MAXN; 63 for(int i = 1; Hash[k] != -hinf; i *= i) { 64 if(Hash[k] == x) { 65 ind = k; 66 return true; 67 } 68 k += i; 69 k %= MAXN; 70 } 71 ind = k; 72 return false; 73 } 74 void init() { 75 FF(i, MAXN) 76 Hash[i] = -hinf; 77 memset(hashVal, 0, sizeof(hashVal)); 78 } 79 }; 80 myHash H; 81 82 void create() { 83 int g = S; 84 for (int i=0; i<N; i++) { 85 a[i] = g; 86 if( a[i] == 0 ) { a[i] = g = W; } 87 if( g%2 == 0 ) { g = (g/2); } 88 else { g = (g/2) ^ W; } 89 } 90 //viewP(a, N); 91 ll t = N; 92 ll sol = (t+1)*t / 2; 93 ll canot = 0; 94 dp[0] = a[0]; 95 if(!dp[0]) 96 canot++; 97 FOR(i, 1, N) { 98 dp[i] = dp[i-1] ^ a[i]; 99 if(!dp[i]) 100 canot++; 101 } 102 103 H.init(); 104 for(int i = 0; i < N; i++) { 105 H.get_key(dp[i], H.k); 106 H.Hash[H.k] = dp[i]; 107 H.hashVal[H.k]++; 108 } 109 for(int i = 0; i < N-1; i++) { 110 if(H.get_key(dp[i], H.k)) { 111 if(H.hashVal[H.k] >= 1) 112 H.hashVal[H.k]--; 113 } 114 canot += H.hashVal[H.k]; 115 } 116 printf("%lld\n", sol - canot); 117 } 118 119 int main() 120 { 121 #ifndef ONLINE_JUDGE 122 //freopen("in.txt", "r", stdin); 123 #endif 124 int cas; 125 scanf("%d", &cas); 126 while(cas--) { 127 scanf("%d%d%d", &N, &S, &W); 128 create(); 129 } 130 return 0; 131 }