感觉这场题面有点绕
A:先把能除2的都除2,然后最后再把最大的不断翻倍即可
// Author: levil #include<bits/stdc++.h> using namespace std; typedef long long LL; typedef unsigned long long ULL; typedef long double ld; typedef pair<int,int> pii; const int N = 2e3 + 5; const int M = 1e4 + 5; const LL Mod = 1e9 + 7; #define rep(at,am,as) for(int at = am;at <= as;++at) #define ret(at,am,as) for(int at = am;at >= as;--at) #define INF 1e9 #define dbg(ax) cout << "now this num is " << ax << endl; inline long long ADD(long long x,long long y) { if(x + y < 0) return ((x + y) % Mod + Mod) % Mod; return (x + y) % Mod; } inline long long MUL(long long x,long long y) { if(x * y < 0) return ((x * y) % Mod + Mod) % Mod; return x * y % Mod; } inline long long DEC(long long x,long long y) { if(x - y < 0) return (x - y + Mod) % Mod; return (x - y) % Mod; } int n,a[N]; void solve() { scanf("%d",&n); for(int i = 1;i <= n;++i) scanf("%d",&a[i]); int cnt = 0,pos; LL mx = 0; for(int i = 1;i <= n;++i) { while(a[i] % 2 == 0) a[i] /= 2,++cnt; if(a[i] * 1LL > mx) mx = a[i],pos = i; } LL ans = 0; for(int i = 1;i <= n;++i) { if(i != pos) ans += a[i]; else { LL tmp = a[i]; for(int j = 1;j <= cnt;++j) tmp *= 2; ans += tmp; } } printf("%lld\n",ans); } int main() { int _; for(scanf("%d",&_);_;_--) { solve(); } //system("pause"); return 0; }
B:演爆了。
// Author: levil #include<bits/stdc++.h> using namespace std; typedef long long LL; typedef unsigned long long ULL; typedef long double ld; typedef pair<int,int> pii; const int N = 1e5 + 5; const int M = 1e4 + 5; const LL Mod = 1e9 + 7; #define rep(at,am,as) for(int at = am;at <= as;++at) #define ret(at,am,as) for(int at = am;at >= as;--at) #define INF 1e9 #define dbg(ax) cout << "now this num is " << ax << endl; inline long long ADD(long long x,long long y) { if(x + y < 0) return ((x + y) % Mod + Mod) % Mod; return (x + y) % Mod; } inline long long MUL(long long x,long long y) { if(x * y < 0) return ((x * y) % Mod + Mod) % Mod; return x * y % Mod; } inline long long DEC(long long x,long long y) { if(x - y < 0) return (x - y + Mod) % Mod; return (x - y) % Mod; } char s[N]; int n,q; bool check(int id,char t) { if(id <= n - 2 && t == 'a' && s[id] == 'b' && s[id + 1] == 'c') return true; if(id <= n - 1 && id >= 2 && t == 'b' && s[id - 2] == 'a' && s[id] == 'c') return true; if(id >= 3 && t == 'c' && s[id - 2] == 'b' && s[id - 3] == 'a') return true; return false; } void solve() { scanf("%d %d",&n,&q); cin >> s; int ans = 0; for(int i = 0;i < n;++i) { if(i + 2 >= n) break; if(s[i] == 'a' && s[i + 1] == 'b' && s[i + 2] == 'c') ans++; } while(q--) { int id; string t; cin >> id >> t; if(t[0] == s[id - 1]) {printf("%d\n",ans);continue;} if(check(id,t[0])) ans++; if(check(id,s[id - 1])) ans--; printf("%d\n",ans); s[id - 1] = t[0]; } } int main() { // int _; // for(scanf("%d",&_);_;_--) { solve(); //} // system("pause"); return 0; }
C:倒着dp即可,用e来判断
// Author: levil #include<bits/stdc++.h> using namespace std; typedef long long LL; typedef unsigned long long ULL; typedef long double ld; typedef pair<int,int> pii; const int N = 2e5 + 5; const int M = 1e6 + 5; const LL Mod = 1e9 + 7; #define rep(at,am,as) for(int at = am;at <= as;++at) #define ret(at,am,as) for(int at = am;at >= as;--at) #define INF 1e9 #define dbg(ax) cout << "now this num is " << ax << endl; inline long long ADD(long long x,long long y) { if(x + y < 0) return ((x + y) % Mod + Mod) % Mod; return (x + y) % Mod; } inline long long MUL(long long x,long long y) { if(x * y < 0) return ((x * y) % Mod + Mod) % Mod; return x * y % Mod; } inline long long DEC(long long x,long long y) { if(x - y < 0) return (x - y + Mod) % Mod; return (x - y) % Mod; } int n,e,a[M]; bool vis[M]; int prime[M],tot = 0; void init() { for(int i = 2;i < M;++i) { if(!vis[i]) prime[++tot] = i; for(int j = 1;j <= tot && prime[j] * i < M;++j) { vis[prime[j] * i] = 1; if(i % prime[j] == 0) break; } } } int dp[M],cnt[M];//0 - not 1 void solve() { scanf("%d %d",&n,&e); for(int i = 1;i <= n;++i) scanf("%d",&a[i]); for(int i = 1;i <= (n + e + 5);++i) dp[i] = cnt[i] = 0; LL ans = 0; ret(i,n,1) { cnt[i] = cnt[i + e] + 1; if(a[i] == 1) { dp[i] = dp[i + e]; if(dp[i] != 0) { if(vis[a[dp[i]]]) continue; if(dp[dp[i] + e] == 0 || dp[i] + e > n) ans += cnt[dp[i]]; else { ans += cnt[dp[i]] - cnt[dp[dp[i] + e]]; } } } else { if(!vis[a[i]]) { if(i + e <= n) { if(dp[i + e] == 0) ans += cnt[i + e]; else { ans += cnt[i] - cnt[dp[i + e]] - 1; } } } dp[i] = i; } } printf("%lld\n",ans); } int main() { init(); int _; for(scanf("%d",&_);_;_--) { solve(); } // system("pause"); return 0; }
D:什么逆天题意。
多的边直接连其他连通块即可。
// Author: levil #include<bits/stdc++.h> using namespace std; typedef long long LL; typedef unsigned long long ULL; typedef long double ld; typedef pair<int,int> pii; const int N = 1e3 + 5; const int M = 1e6 + 5; const LL Mod = 1e9 + 7; #define rep(at,am,as) for(int at = am;at <= as;++at) #define ret(at,am,as) for(int at = am;at >= as;--at) #define INF 1e9 #define dbg(ax) cout << "now this num is " << ax << endl; inline long long ADD(long long x,long long y) { if(x + y < 0) return ((x + y) % Mod + Mod) % Mod; return (x + y) % Mod; } inline long long MUL(long long x,long long y) { if(x * y < 0) return ((x * y) % Mod + Mod) % Mod; return x * y % Mod; } inline long long DEC(long long x,long long y) { if(x - y < 0) return (x - y + Mod) % Mod; return (x - y) % Mod; } int fa[N],ans[N],sz[N]; int Find(int x) {return x == fa[x] ? x : fa[x] = Find(fa[x]);} bool vis[N][N]; void solve() { int n,d;scanf("%d %d",&n,&d); for(int i = 1;i <= n;++i) fa[i] = i,sz[i] = 1; int cnt = 0; while(d--) { int ans = 0; int x,y;scanf("%d %d",&x,&y); int xx = Find(x),yy = Find(y); vector<int> vec; if(xx != yy) { fa[xx] = yy,sz[yy] += sz[xx]; } else cnt++; rep(i,1,n) if(i == Find(i)) vec.push_back(sz[i]); sort(vec.begin(),vec.end(),greater<int>()); rep(i,1,min((int)vec.size(),cnt + 1)) ans += vec[i - 1]; printf("%d\n",ans - 1); } } int main() { //int _; //for(scanf("%d",&_);_;_--) { solve(); //} //system("pause"); return 0; }
E:这题还是挺不错的。
线段树上维护一个dp。
首先我们考虑一下状压一下状态,第0位代表a,第1位代表b,第2位代表c,第3位代表ab,第4位代表bc。
dp[i] - 表示序列中只包含状态i的情况。
首先问题就是为什么只有这几种情况,因为只有他们对答案有影响,其他的都可以当场什么状态都没的情况即0。
然后就是两个序列合并之后产生的情况,需要充分考虑,然后对于ab这种,其实a和b状态必定包含在里面,所以必须要算上。
合并的时候就是dp[i][j] = min{dp[i][k] + dp[k][j]},类似Floyd。
有点像DFA上的Floyd.
// Author: levil #include<bits/stdc++.h> using namespace std; typedef long long LL; typedef unsigned long long ULL; typedef long double ld; typedef pair<int,int> pii; const int N = 1e5 + 5; const int M = 1e6 + 5; const LL Mod = 1e9 + 7; #define rep(at,am,as) for(int at = am;at <= as;++at) #define ret(at,am,as) for(int at = am;at >= as;--at) #define INF 1e9 #define dbg(ax) cout << "now this num is " << ax << endl; inline long long ADD(long long x,long long y) { if(x + y < 0) return ((x + y) % Mod + Mod) % Mod; return (x + y) % Mod; } inline long long MUL(long long x,long long y) { if(x * y < 0) return ((x * y) % Mod + Mod) % Mod; return x * y % Mod; } inline long long DEC(long long x,long long y) { if(x - y < 0) return (x - y + Mod) % Mod; return (x - y) % Mod; } int n,q; char s[N]; struct Node{int L,r,dp[1 << 5];}node[N << 2];//0 - a,1 - b,2 - c,3 - ab,4 - bc int Merge[1 << 5][1 << 5]; bool ishav(int i,int k) { if((i >> k) & 1) return true; else return false; } bool judge(int i,int j) { if(ishav(i,0) && ishav(j,4)) return false; if(ishav(i,3) && (ishav(j,4) || ishav(j,2))) return false; return true; } void init() { rep(i,0,(1 << 5) - 1) { rep(j,0,(1 << 5) - 1) { if(!judge(i,j)) Merge[i][j] = -1; else { rep(k,0,4) if(ishav(i,k) || ishav(j,k)) Merge[i][j] |= (1 << k); if(ishav(i,0) && ishav(j,1)) Merge[i][j] |= (1 << 3); if(ishav(i,1) && ishav(j,2)) Merge[i][j] |= (1 << 4); if(ishav(i,3) || ishav(j,3)) Merge[i][j] |= (1 << 0),Merge[i][j] |= (1 << 1); if(ishav(i,4) || ishav(j,4)) Merge[i][j] |= (1 << 1),Merge[i][j] |= (1 << 2); } } } // rep(i,0,(1 << 5) - 1) { // rep(j,0,(1 << 5) - 1) { // printf("mask[%d][%d] is %d\n",i,j,Merge[i][j]); // } // } } void Pushup(int idx) { int ls = idx << 1,rs = idx << 1 | 1; rep(i,0,(1 << 5) - 1) node[idx].dp[i] = INF; rep(i,0,(1 << 5) - 1) { rep(j,0,(1 << 5) - 1) { if(Merge[i][j] == -1) continue; node[idx].dp[Merge[i][j]] = min(node[idx].dp[Merge[i][j]],node[ls].dp[i] + node[rs].dp[j]); } } } void build(int L,int r,int idx) { node[idx].L = L,node[idx].r = r; rep(i,0,(1 << 5) - 1) node[idx].dp[i] = INF; if(L == r) { int val = s[L -1] - 'a'; node[idx].dp[1 << val] = 0; node[idx].dp[0] = 1; return ; } int mid = (L + r) >> 1; build(L,mid,idx << 1); build(mid + 1,r,idx << 1 | 1); Pushup(idx); } void modify(int x,char c,int idx) { if(node[idx].L == node[idx].r) { rep(i,0,(1 << 5) - 1) node[idx].dp[i] = INF; int val = c - 'a'; node[idx].dp[1 << val] = 0; node[idx].dp[0] = 1; return ; } int mid = (node[idx].L + node[idx].r) >> 1; if(mid >= x) modify(x,c,idx << 1); else modify(x,c,idx << 1 | 1); Pushup(idx); } void solve() { init(); scanf("%d %d",&n,&q); scanf("%s",s); build(1,n,1); while(q--) { int x;char c; scanf("%d",&x);getchar(); c = getchar(); if(s[x - 1] != c) modify(x,c,1),s[x - 1] = c; int ans = INF; rep(i,0,(1 << 5) - 1) ans = min(ans,node[1].dp[i]); printf("%d\n",ans); } } int main() { //int _; //for(scanf("%d",&_);_;_--) { solve(); //} system("pause"); return 0; }