找相同顏色的一段,而後答案加上段長除2下取整node
#include <iostream> #include <cstdio> using namespace std; int N; int a[105]; int main() { scanf("%d",&N); for(int i = 1 ; i <= N ; ++i) { scanf("%d",&a[i]); } int ans = 0; int cnt = 0; for(int i = 1 ; i <= N ; ++i) { if(a[i] != a[i - 1]) { ans += cnt / 2; cnt = 0; } ++cnt; } ans += cnt / 2; printf("%d\n",ans); }
若是A < B必定不能夠
若是C>=B而且D>=B顯然必定能夠
若是D < B那麼必定不能夠
而後若是A大於C,那麼就買幾個B使得A減到C如下,若是減的過程當中買不到了,那麼就不能夠ios
每次買完還須要補貨的時候至關於從A開始,每次加上B和D的gcd,若是這個值落在了C和B之間,那麼就不合法了spa
#include <iostream> #include <cstdio> #include <algorithm> #include <vector> #include <cstring> //#define ivorysi #define fi first #define se second #define MAXN 25005 #define enter putchar('\n') #define space putchar(' ') typedef long long int64; using namespace std; template <class T> void read(T &res) { res = 0;char c = getchar();T f = 1; while(c < '0' || c > '9') { c = getchar(); if(c == '-') f = -1; } while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); } res *= f; } template <class T> void out(T x) { if(x < 0) {x = -x;} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } int T; int64 A,B,C,D; int64 gcd(int64 a,int64 b) { return b == 0 ? a : gcd(b,a % b); } void Solve() { read(A);read(B);read(C);read(D); if(A < B) {puts("No");} else { if(C >= B && D >= B) puts("Yes"); else if(D < B) puts("No"); else { if(A > C) { int64 t = (A - C - 1) / B + 1; if(t > A / B) { puts("No");return; } A -= B * t; } int64 g = gcd(D % B,B); if((C + 1 - A - 1) / g + 1 == (B - A - 1) / g + 1) puts("Yes"); else puts("No"); } } } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif read(T); while(T--) { Solve(); } }
直接折半搜索便可
用哈希表維護前半部分拆分方式的兩個字符串的哈希值
再枚舉後一半的拆分方式查哈希表便可code
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #define enter putchar('\n') #define space putchar(' ') #define fi first #define se second #define ba 47 #define mo 999999137 #define mod 974711 //#define ivorysi #define pii pair<int,int> using namespace std; typedef long long int64; template<class T> void read(T &res) { res = 0;char c = getchar();T f = 1; while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {putchar('-');x = -x;} if(x >= 10) out(x / 10); putchar('0' + x % 10); } struct Hash { char t[20]; int64 val; int len; friend bool operator < (const Hash &a,const Hash &b) { return a.val < b.val; } friend bool operator == (const Hash &a,const Hash &b) { if(a.val != b.val) return false; if(a.len != b.len) return false; for(int i = 1 ; i <= a.len ; ++i) { if(a.t[i] != b.t[i]) return false; } return true; } }B[1000005]; int cnt; int64 e[55]; struct Mmp { struct node { int next,v; int64 x; }E[1000005]; int head[mod + 5],sumE; void clear() { memset(head,0,sizeof(head)); sumE = 0; } void add(int64 x,int v) { int u = x % mod; E[++sumE].x = x; E[sumE].v = v; E[sumE].next = head[u]; head[u] = sumE; } void Insert(int64 x) { int u = x % mod; for(int i = head[u] ; i ; i = E[i].next) { if(E[i].x == x) {E[i].v++;return;} } add(x,1); } int Query(int64 x) { int u = x % mod; for(int i = head[u]; i ; i = E[i].next) { if(E[i].x == x) return E[i].v; } return 0; } }M1,M2; int64 Calc(char *s,int l) { int64 res = 0; for(int i = 1 ; i <= l ; ++i) { res += (s[i] - 'a' + 1) * e[i] % mo; res %= mo; } return res; } void Insert(char *s,int l) { ++cnt; for(int i = 1 ; i <= l ; ++i) B[cnt].t[i] = s[i]; B[cnt].len = l;B[cnt].val = Calc(s,l); } int N; char s[55]; void Solve() { read(N); e[0] = 1; for(int i = 1 ; i <= N ; ++i) e[i] = e[i - 1] * ba % mo; scanf("%s",s + 1); char t1[25],t2[25]; int c1,c2; for(int S = 0 ; S < (1 << N) ; ++S) { c1 = c2 = 0; int T = 0; for(int i = 1 ; i <= N ; ++i) { if(S >> (i - 1) & 1) t1[++c1] = s[i]; else {t2[++c2] = s[i];T |= (1 << i - 1);} } if(S > T) continue; if(c1) Insert(t1,c1); if(c2) Insert(t2,c2); } sort(B + 1,B + cnt + 1); cnt = unique(B + 1,B + cnt + 1) - B - 1; M1.clear();M2.clear(); for(int i = 1 ; i <= cnt ; ++i) { M1.add(B[i].val,i); } for(int S = 0 ; S < (1 << N) ; ++S) { c1 = c2 = 0; for(int i = 1 ; i <= N ; ++i) { if(S >> (i - 1) & 1) t1[++c1] = s[i]; else {t2[++c2] = s[i];} } int d1 = 0,d2 = 0; if(c1) d1 = M1.Query(Calc(t1,c1)); if(c2) d2 = M1.Query(Calc(t2,c2)); M2.Insert(1LL * d1 * (cnt + 1) + d2); } int64 ans = 0; for(int S = 0 ; S < (1 << N) ; ++S) { c1 = c2 = 0; for(int i = N + 1 ; i <= 2 * N ; ++i) { if(S >> (i - N - 1) & 1) t1[++c1] = s[i]; else {t2[++c2] = s[i];} } reverse(t1 + 1,t1 + c1 + 1); reverse(t2 + 1,t2 + c2 + 1); int d1 = 0,d2 = 0; if(c1) d1 = M1.Query(Calc(t1,c1)); if(c2) d2 = M1.Query(Calc(t2,c2)); ans += M2.Query(1LL * d1 * (cnt + 1) + d2); } out(ans);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); }
咱們考慮從上往下,對於每一個分離的直方圖的橫列進行dp,而後再把他們合起來字符串
咱們發現,若是直方圖不是10101010或0101010101的形式,那麼如下全部列就只有一種放置方法get
那麼咱們記錄兩個值,一個是直方圖最下面一行填的是1010101或01010101,記爲dp[S][1],一個是全部的方案數記爲dp[S][2]string
轉移方法是對於一個列數同樣的矩形塊
dp[S][1]是它上面全部的直方圖dp[S][1]乘起來,而後再乘上2的行數次冪
dp[S][2]咱們認爲是若是是010101或101010,那麼下面對應的有兩種方式,剩下的只有一種,其他的方塊隨便填,下面每一行是上一行取反
是上面全部直方圖的(dp[T][1] + dp[T][2])乘起來,而後再乘上2的剩餘方塊數的冪
可是dp[S][2]也應該包括相鄰兩行有相同的狀況,咱們就再加上dp[S][1],同時減掉dp[S][1]中咱們每行都不一樣的狀況it
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #define enter putchar('\n') #define space putchar(' ') #define fi first #define se second #define mp make_pair #define ba 47 #define mo 999999137 #define mod 974711 //#define ivorysi #define pii pair<int,int> using namespace std; typedef long long int64; template<class T> void read(T &res) { res = 0;char c = getchar();T f = 1; while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {putchar('-');x = -x;} if(x >= 10) out(x / 10); putchar('0' + x % 10); } const int MOD = 1000000007; int N; int h[105]; bool vis[105]; int inc(int a,int b) { return a + b >= MOD ? a + b - MOD : a + b; } int mul(int a,int b) { return 1LL * a * b % MOD; } int fpow(int x,int c) { int res = 1,t = x; while(c) { if(c & 1) res = mul(res,t); t = mul(t,t); c >>= 1; } return res; } void update(int &x,int y) { x = inc(x,y); } pii Solve(int l,int r,int v) { int minv = 1e9; for(int i = l ; i <= r ; ++i) minv = min(minv,h[i]); int p,cnt = 0; pii res = mp(1,1); for(int i = l ; i <= r ; ++i) { if(h[i] > minv) ++cnt; } for(int i = l ; i <= r ; ++i) { if(h[i] > minv) { p = i; while(p < r && h[p + 1] > minv) ++p; pii f = Solve(i,p,minv); res.fi = mul(res.fi,f.fi); res.se = mul(res.se,inc(f.se,f.fi)); i = p; } } int t = mul(res.fi,2); res.se = mul(res.se,fpow(2,r - l + 1 - cnt)); res.fi = mul(res.fi,fpow(2,minv - v)); res.se = inc(res.se,inc(res.fi,MOD - t)); return res; } void Solve() { read(N); for(int i = 1 ; i <= N ; ++i) {read(h[i]);} pii ans = Solve(1,N,0); out(ans.se);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); }
若是b在a前就一直選,選到某個最大的a的位置會更改爲一段a在b前
若是這個a在b前是最後一部分就取到全部的abababab...前,不然就跳過這一段
具體就用string維護一下後綴能取到的max字符串就行了io
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <cmath> #include <queue> #include <ctime> #include <map> #include <set> #define fi first #define se second #define pii pair<int,int> //#define ivorysi #define mp make_pair #define pb push_back #define enter putchar('\n') #define space putchar(' ') #define MAXN 6005 using namespace std; typedef long long int64; typedef double db; typedef unsigned int u32; template<class T> void read(T &res) { res = 0;T f = 1;char c = getchar(); while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9' ) { res = res * 10 - '0' + c; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } namespace task { char s[MAXN]; int N,a[MAXN],b[MAXN],tota,totb,pos[MAXN]; string str[MAXN]; bool vis[MAXN]; void Init() { read(N); scanf("%s",s + 1); tota = 0;totb = 0; for(int i = 1 ; i <= 2 * N ; ++i) { if(s[i] == 'a') {a[++tota] = i;pos[i] = tota;} else {b[++totb] = i;pos[i] = totb;} } } void Solve() { str[2 * N + 1] = ""; for(int i = 2 * N ; i >= 1 ; --i) { str[i] = max(str[i],str[i + 1]); string t = ""; int p = pos[i]; if(s[i] == 'a' && a[p] < b[p]) { str[i] = max(str[i],"ab" + str[b[p] + 1]); } else if(s[i] == 'b' && b[p] < a[p]) { memset(vis,0,sizeof(vis)); int maxv = a[p]; for(int j = i ; j <= maxv ; ++j) { if(s[j] == 'b') { p = pos[j]; vis[b[p]] = 1;vis[a[p]] = 1; maxv = max(a[p],maxv); } if(vis[j]) t += s[j]; } t += str[maxv + 1]; str[i] = max(str[i],t); } } cout<<str[1]<<endl; } } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif task::Init(); task::Solve(); return 0; }
咱們把整個序列黑白染色變成
BWBWBWBW的形式class
若是是偶數的話
先手能夠保證本身獲得所有的B或所有的W
後手能夠在先手作出選擇後,保證本身獲得另外一種顏色的全部
這樣的話,至關於先手獲得黑白顏色中較多的那個,後手獲得較少的那個
若是是奇數的話
先手仍是能夠保證本身獲得全部B
那麼先手選W的話解會不會更優
先手在選B以後,便不可能再選W,若是某一次B進行完了之後先手選了W結果更優,後手能夠撤銷上一次操做,使得前後手所拿到的物品相反,結果更劣
先手假如能夠選\(W_1,W_2,W_3...W_k\)若是,咱們能取的區間若是全取B的話,這個區間的B - W是最小的,因此咱們限定一下這個區間B - W的最小值,二分一下,而後用一個dp判斷便可
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #define enter putchar('\n') #define space putchar(' ') #define fi first #define se second #define mp make_pair //#define ivorysi #define pii pair<int,int> using namespace std; typedef long long int64; template<class T> void read(T &res) { res = 0;char c = getchar();T f = 1; while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {putchar('-');x = -x;} if(x >= 10) out(x / 10); putchar('0' + x % 10); } int N; int64 a[300005],sum[300005][2]; bool check(int64 mid) { int64 t = 0; for(int i = 2 ; i <= N ; i += 2) { if(sum[i - 1][1] - sum[i - 1][0] + t >= mid) { t = max(sum[i][0] - sum[i][1],t); } } if(sum[N][1] - sum[N][0] + t >= mid) return true; return false; } void Solve() { read(N); for(int i = 1 ; i <= N ; ++i) read(a[i]); int64 L = 0,R = 0; for(int i = 1 ; i <= N ; ++i) { R += a[i];L -= a[i]; sum[i][0] = sum[i - 1][0]; sum[i][1] = sum[i - 1][1]; sum[i][i & 1] += a[i]; } if(N % 2 == 0) { out(max(sum[N][0],sum[N][1]));space;out(min(sum[N][0],sum[N][1]));enter; return; } while(L < R) { int64 mid = (L + R + 1) >> 1; if(check(mid)) L = mid; else R = mid - 1; } int64 a = L + sum[N][0]; int64 b = sum[N][0] + sum[N][1] - a; out(a);space;out(b);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); }