直接分解質因數,而後gcd每次多一個質因數均攤到每一個\(N\)上的個數c++
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #define enter putchar('\n') #define space putchar(' ') #define eps 1e-8 #define mo 974711 #define MAXN 200005 //#define ivorysi using namespace std; typedef long long int64; typedef double db; 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) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } int64 N,P; int64 g = 1; int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif read(N);read(P); if(N == 1) {out(P);enter;return 0;} for(int64 i = 2 ; i <= P / i ; ++i) { if(P % i == 0) { int64 cnt = 0; while(P % i == 0) {P /= i;++cnt;} int64 k = cnt / N; while(k--) g *= i; } } out(g);enter; return 0; }
這題簡直了,比賽完兩分鐘就想出來,比賽時候硬是怎麼也想不出來ui
若是全是偶數確定後手必勝,由於先手在哪一個堆拿一個後手在這個堆跟一個
若是某個堆是奇數先手能夠把局面轉變爲全是偶數而後本身當後手spa
因此有奇數先手必勝
全是偶數後手必勝code
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #define enter putchar('\n') #define space putchar(' ') #define eps 1e-8 #define mo 974711 #define MAXN 200005 //#define ivorysi using namespace std; typedef long long int64; typedef double db; 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) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } int N; int a[MAXN],cnt[2]; int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif read(N); for(int i = 1 ; i <= N ; ++i) read(a[i]); for(int i = 1 ; i <= N ; ++i) { if(a[i] & 1) {puts("first");return 0;} } puts("second"); return 0; }
有點麻煩的一道題,想起來容易寫起來不容易
就是我對於每一個序列確定是要求不斷乘4使得序列不降,正着反着都要算
就說從\(1-N\)不降
咱們從後往前加數
若是加的這個數比它的後一個小,那麼\(dp[i] = dp[i + 1]\)
不然後一個數確定會變大,後一個數變大會引發以後的一些值變大,若是和後面相連且已經增長過的位置都會同時加上這個數,同時這個增長了還會使後面沒有增長過的位置增長
這個能夠用鏈表維護,由於每一個點被增長後就被刪除了,因此鏈表維護每次暴力更新就好get
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #define enter putchar('\n') #define space putchar(' ') #define eps 1e-8 #define mo 974711 #define MAXN 200005 //#define ivorysi using namespace std; typedef long long int64; typedef double db; 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) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } int N,val[MAXN],pre[MAXN],suf[MAXN]; int64 a[MAXN],dp[2][MAXN],ans; void Init() { read(N); for(int i = 1 ; i <= N ; ++i) read(a[i]); } void Solve() { suf[0] = 1; for(int i = 1 ; i <= N ; ++i) suf[i] = i + 1,pre[i] = i - 1; pre[N + 1] = N; for(int i = N ; i > 1 ; --i) { if(a[i] >= a[i - 1]) { int64 t = a[i]; while(t / 4 >= a[i - 1]) {val[i] -= 2; t /= 4;} } else { int64 t = a[i]; while(t < a[i - 1]) {val[i] += 2; t *= 4;} } } for(int i = N - 1 ; i >= 1 ; --i) { dp[0][i] = dp[0][i + 1]; if(a[i] > a[i + 1]) { int t = val[i + 1],p = i + 1; while(1) { dp[0][i] += 1LL * t * (suf[p] - p); if(suf[p] - 1 != p) val[suf[p] - 1] += t; if(val[suf[p] - 1] + val[suf[p]] <= 0) break; if(suf[p] == N + 1) break; t = val[suf[p] - 1] + val[suf[p]]; p = suf[p];val[p] = t; pre[suf[p]] = pre[p];suf[pre[p]] = suf[p]; } pre[suf[i + 1]] = pre[i + 1]; suf[pre[i + 1]] = suf[i + 1]; } } suf[0] = 1; for(int i = 1 ; i <= N ; ++i) pre[i] = i - 1,suf[i] = i + 1; pre[N + 1] = N; memset(val,0,sizeof(val)); for(int i = 1 ; i < N ; ++i) { if(a[i] < a[i + 1]) { int64 t = a[i]; while(t < a[i + 1]) {t *= 4;val[i] += 2;} } else { int64 t = a[i]; while(t / 4 >= a[i + 1]) {t /= 4;val[i] -= 2;} } } for(int i = 2 ; i <= N ; ++i) { dp[1][i] = dp[1][i - 1]; if(a[i] > a[i - 1]) { int t = val[i - 1],p = i - 1; while(1) { dp[1][i] += 1LL * t * (p - pre[p]); if(pre[p] + 1 != p) val[pre[p] + 1] += t; if(val[pre[p] + 1] + val[pre[p]] <= 0) break; if(pre[p] == 0) break; t = val[pre[p] + 1] + val[pre[p]]; p = pre[p];val[p] = t; pre[suf[p]] = pre[p];suf[pre[p]] = suf[p]; } pre[suf[i - 1]] = pre[i - 1]; suf[pre[i - 1]] = suf[i - 1]; } } int64 ans = dp[0][1]; for(int i = 1 ; i <= N ; ++i) { ans = min(dp[1][i] + i + dp[0][i + 1],ans); } out(ans);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Init(); Solve(); return 0; }
咱們冷靜一下很容易發現若是\(abs(x - y) > 2\)那麼\((x,y)\)上的數加上\((y,x)\)的數確定是偶數
這樣的話咱們統計一下沒被佔的對數,以及若是兩個位置都有值是否合法,假如對數是\(cnt\),最後的答案要乘上\(2^cnt\)it
這樣的話咱們只要對中間那一段\(abs(x - y) <= 2\)的部分dp就行了
咱們記錄中軸線上的點,中軸上的點能夠肯定\((i - 1,i + 1)\)和\((i + 1,i - 1)\)的奇偶性
\((i - 1,i - 1)\)和\((i,i)\)能夠肯定\((i - 1,i)\)和\((i,i - 1)\)的奇偶性,判一下就行class
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #define enter putchar('\n') #define space putchar(' ') #define eps 1e-8 #define mo 974711 #define MAXN 100005 //#define ivorysi using namespace std; typedef long long int64; typedef double db; 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) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } const int MOD = 998244353; int N,M; int a[MAXN],b[MAXN],c[MAXN],dp[MAXN][2]; int d[MAXN][4][4]; map<pii,int> zz; 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 Init() { read(N);read(M); for(int i = 1 ; i <= N ; ++i) memset(d[i],-1,sizeof(d[i])); for(int i = 1 ; i <= M ; ++i) { read(a[i]);read(b[i]);read(c[i]); zz[mp(a[i],b[i])] = c[i]; if(abs(a[i] - b[i]) <= 2) { int s = a[i],t = b[i]; if(s > t) swap(s,t); for(int k = s - 1 ; k <= t + 1 ; ++k) { if(k < 0 || k > N) continue; if(abs(a[i] - k) <= 1 && abs(b[i] - k) <= 1) { d[k][2 - (k - a[i])][2 - (k - b[i])] = c[i]; } } } } } void Solve() { int64 cnt = 1LL * N * N; if(N == 2) cnt = 0; else cnt -= (N - 3) * 5 + 9; cnt /= 2; for(int i = 1 ; i <= M ; ++i) { if(abs(b[i] - a[i]) <= 2) continue; if(zz.count(mp(b[i],a[i]))) { if((zz[mp(b[i],a[i])] + c[i]) & 1) {puts("0");return;} if(a[i] < b[i]) --cnt; } else --cnt; } int ans = fpow(2,cnt % (MOD - 1)); if(zz.count(mp(1,1))) dp[1][zz[mp(1,1)]] = 1; else dp[1][0] = dp[1][1] = 1; for(int i = 2 ; i <= N ; ++i) { int t = 1; if(d[i][1][2] == -1 && d[i][2][1] == -1) t = mul(t,2); if(d[i][1][3] == -1 && d[i][3][1] == -1 && i != N) t = mul(t,2); for(int k = 0 ; k <= 1 ; ++k) { if(d[i][2][2] != -1 && d[i][2][2] != k) continue; if(d[i][1][3] != -1 && d[i][3][1] != -1 && (d[i][1][3] ^ d[i][3][1]) != k) continue; for(int h = 0 ; h <= 1 ; ++h) { if(!dp[i - 1][h]) continue; if(d[i][1][2] != -1 && d[i][2][1] != -1 && (d[i][2][1] ^ d[i][1][2]) != (k ^ h)) continue; dp[i][k] = inc(dp[i][k],mul(t,dp[i - 1][h])); } } } ans = mul(ans,inc(dp[N][0],dp[N][1])); out(ans);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Init(); Solve(); return 0; }