codeforces - 808 (div2)
A.把这个数+1,如果符合条件就符合条件了,不符合就把最高位 + 1,其余位置0
#include <map> #include <set> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <bitset> #include <cstdio> #include <cstdlib> #include <cstring> #include <sstream> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define For(i, x, y) for(int i=x;i<=y;i++) #define _For(i, x, y) for(int i=x;i>=y;i--) #define Mem(f, x) memset(f,x,sizeof(f)) #define Sca(x) scanf("%d", &x) #define Sca2(x,y) scanf("%d%d",&x,&y) #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define Scl(x) scanf("%lld",&x) #define Pri(x) printf("%d\n", x) #define Prl(x) printf("%lld\n",x) #define CLR(u) for(int i=0;i<=N;i++)u[i].clear(); #define LL long long #define ULL unsigned long long #define mp make_pair #define PII pair<int,int> #define PIL pair<int,long long> #define PLL pair<long long,long long> #define pb push_back #define fi first #define se second typedef vector<int> VI; int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();} while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;} const double eps = 1e-9; const int maxn = 110; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; LL N,M,K; int cul(LL x){ int ans = 0; while(x){ if(x % 10) ans++; x /= 10; } return ans; } int main(){ Scl(N); LL x = N + 1; int num = cul(x); if(num == 1){ Pri(1); return 0; } int p = 0; do{ p++; x /= 10; }while(x >= 10); x++; for(int i = 0 ; i < p ;i ++) x *= 10; Prl(x - N); return 0; }
B.列几下就找到规律,每个数加的次数是呈阶梯状的,例如 1 2 3 3 3 3 3 2 1,阶梯顶的值由星期数和K的最小值决定
#include <map> #include <set> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <bitset> #include <cstdio> #include <cstdlib> #include <cstring> #include <sstream> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define For(i, x, y) for(int i=x;i<=y;i++) #define _For(i, x, y) for(int i=x;i>=y;i--) #define Mem(f, x) memset(f,x,sizeof(f)) #define Sca(x) scanf("%d", &x) #define Sca2(x,y) scanf("%d%d",&x,&y) #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define Scl(x) scanf("%lld",&x) #define Pri(x) printf("%d\n", x) #define Prl(x) printf("%lld\n",x) #define CLR(u) for(int i=0;i<=N;i++)u[i].clear(); #define LL long long #define ULL unsigned long long #define mp make_pair #define PII pair<int,int> #define PIL pair<int,long long> #define PLL pair<long long,long long> #define pb push_back #define fi first #define se second typedef vector<int> VI; int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();} while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;} const double eps = 1e-9; const int maxn = 2e5 + 10; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; int N,M,K; long double a[maxn]; int main(){ Sca2(N,M); long double sum = 0; for(int i = 1; i <= N; i ++){ scanf("%Lf",&a[i]); sum += a[i] * min(min(min(i,N - i + 1),M),N - M + 1); } printf("%.10Lf",sum / (N - M + 1)); return 0; }
C.先全部装一半,然后从大杯子往小杯子依次把剩下的水倒完,倒不完的和水不够的都是有问题的
#include <map> #include <set> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <bitset> #include <cstdio> #include <cstdlib> #include <cstring> #include <sstream> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define For(i, x, y) for(int i=x;i<=y;i++) #define _For(i, x, y) for(int i=x;i>=y;i--) #define Mem(f, x) memset(f,x,sizeof(f)) #define Sca(x) scanf("%d", &x) #define Sca2(x,y) scanf("%d%d",&x,&y) #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define Scl(x) scanf("%lld",&x) #define Pri(x) printf("%d\n", x) #define Prl(x) printf("%lld\n",x) #define CLR(u) for(int i=0;i<=N;i++)u[i].clear(); #define LL long long #define ULL unsigned long long #define mp make_pair #define PII pair<int,int> #define PIL pair<int,long long> #define PLL pair<long long,long long> #define pb push_back #define fi first #define se second typedef vector<int> VI; int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();} while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;} const double eps = 1e-9; const int maxn = 110; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; int N,M,K; PII a[maxn]; int b[maxn]; int ans[maxn]; int main(){ Sca2(N,M); int sum = 0; for(int i = 1; i <= N ; i ++) Sca(a[i].fi),a[i].se = i; sort(a + 1,a + 1 + N); for(int i = 1; i <= N ; i ++){ b[i] = a[i].fi / 2; if(a[i].fi & 1) b[i]++; M -= b[i]; } if(M < 0){ puts("-1"); return 0; } for(int i = N; i >= 1 && M; i --){ int t = min(a[i].fi - b[i],M); b[i] += t; M -= t; } if(M){ puts("-1"); return 0; } for(int i = 1; i <= N ; i ++) ans[a[i].se] = b[i]; for(int i = 1; i <= N ; i ++){ printf("%d ",ans[i]); } return 0; }
D.求出前缀和,枚举移动的数字t,然后二分在数字左端寻找pre[i] + t = sum的i,二分在右寻找pre[i] - t = sum的i
找到一次就是YES
#include <map> #include <set> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <bitset> #include <cstdio> #include <cstdlib> #include <cstring> #include <sstream> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define For(i, x, y) for(int i=x;i<=y;i++) #define _For(i, x, y) for(int i=x;i>=y;i--) #define Mem(f, x) memset(f,x,sizeof(f)) #define Sca(x) scanf("%d", &x) #define Sca2(x,y) scanf("%d%d",&x,&y) #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define Scl(x) scanf("%lld",&x) #define Pri(x) printf("%d\n", x) #define Prl(x) printf("%lld\n",x) #define CLR(u) for(int i=0;i<=N;i++)u[i].clear(); #define LL long long #define ULL unsigned long long #define mp make_pair #define PII pair<int,int> #define PIL pair<int,long long> #define PLL pair<long long,long long> #define pb push_back #define fi first #define se second typedef vector<int> VI; int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();} while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;} const double eps = 1e-9; const int maxn = 1e5 + 10; const int INF = 0x3f3f3f3f; const int mod = 1e9; int a[maxn]; LL pre[maxn]; int N; LL sum; bool check(int t) { int l = 0; int r = t - 1; while(l <= r){ int mid = (l + r) / 2; if(pre[mid] + a[t] < sum) l = mid + 1; else if(pre[mid] + a[t] > sum) r = mid - 1; else return true; } l = t; r = N; while(l <= r){ int mid = (l + r) / 2; if(pre[mid] - a[t] < sum) l = mid + 1; else if(pre[mid] - a[t] > sum) r = mid - 1; else return true; } return false; } int main() { Sca(N); sum = 0; for(int i = 1; i <= N ; i ++){ scanf("%d",&a[i]); sum += a[i]; pre[i] = pre[i - 1] + a[i]; } if(sum & 1){ printf("NO\n"); return 0; } sum /= 2; bool flag = 0; for(int i = 1; i <= N && !flag; i ++) if(check(i)) flag = 1; if(flag) printf("YES\n"); else printf("NO\n"); return 0; }
E.感觉是个dp,我的做法肯定不是正解。
把三种重量的背包分类,按照价值从大到小排序然后求出前缀和,那么一定是在1,2,3中选择a,b,c个物品,答案是pre[a] + pre[b] + pre[c]
但是枚举是个O(n²),不能直接做。
所以直接上了模拟退火,模拟a,b,c指针的移动寻找最大值,洗了洗手交了一发就AC了
注:交下面的代码一遍可能A不了,需要洗洗手多交一边
#include <map> #include <set> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <bitset> #include <cstdio> #include <cstdlib> #include <cstring> #include <sstream> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define For(i, x, y) for(int i=x;i<=y;i++) #define _For(i, x, y) for(int i=x;i>=y;i--) #define Mem(f, x) memset(f,x,sizeof(f)) #define Sca(x) scanf("%d", &x) #define Sca2(x,y) scanf("%d%d",&x,&y) #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define Scl(x) scanf("%lld",&x) #define Pri(x) printf("%d\n", x) #define Prl(x) printf("%lld\n",x) #define CLR(u) for(int i=0;i<=N;i++)u[i].clear(); #define LL long long #define ULL unsigned long long #define mp make_pair #define PII pair<int,int> #define PIL pair<int,long long> #define PLL pair<long long,long long> #define pb push_back #define fi first #define se second typedef vector<int> VI; int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();} while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;} const double eps = 1e-9; const int maxn = 1e5 + 10; const int maxm = 3e5 + 10; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; int N,M,K; LL pre[4][maxn],cnt[4]; vector<LL>Q[4]; bool cmp(LL a,LL b){ return a > b; } LL ans,ansa,ansb,ansc; LL cul(LL a,LL b,LL c){ if(a + 2 * b + 3 * c > M) return 0; return pre[1][a] + pre[2][b] + pre[3][c]; } const double delta = 0.999; void s_a(){ double t = 30000; int a = ansa,b = ansb,c = ansc; while(t > 1e-14){ int atmp = a + (rand() * 2 - RAND_MAX) * t; atmp = ((atmp % (Q[1].size() + 1)) + Q[1].size() + 1) % (Q[1].size() + 1); int btmp = b + (rand() * 2 - RAND_MAX) * t; btmp = ((btmp % (Q[2].size() + 1)) + Q[2].size() + 1) % (Q[2].size() + 1); int ctmp = c + (rand() * 2 - RAND_MAX) * t; ctmp = ((ctmp % (Q[3].size() + 1)) + Q[3].size() + 1) % (Q[3].size() + 1); LL new_ans = cul(atmp,btmp,ctmp); LL DE = new_ans - ans; if(DE > 0){ ansa = a = atmp; ansb = b = btmp; ansc = c = ctmp; ans = new_ans; }else if(-exp(-DE / t) * RAND_MAX > rand()){ a = atmp; b = btmp; c = ctmp; } t = t * delta; } } void SA(){ s_a();s_a(); s_a();s_a(); s_a();s_a(); } int main(){ Sca2(N,M); srand(time(NULL)); for(int i = 1; i <= N ; i ++){ LL w = read(),t = read(); Q[w].pb(t); } for(int i = 1; i <= 3; i ++) sort(Q[i].begin(),Q[i].end(),cmp); for(int i = 1; i <= 3; i ++){ for(int j = 0 ; j < Q[i].size(); j ++){ pre[i][j + 1] = pre[i][j] + Q[i][j]; } } ansa = ansb = ansc = 0; SA(); //ACACAC Prl(cul(ansa,ansb,ansc)); return 0; }
F.题目的导向很明显,二分level或者将level排序依次更新答案。
先考虑2分level,如果将题目的意思换一种方式说:对于ci和为质数的两张卡片,必须至少放弃其中一张。
再配上N这个100的范围,思路就呼之欲出了
这是一个类似最大权闭合子图的网络流,建图的方法稍微和最大权闭合子图有些出入
拆所有点i为i和i + N
将所有点S向i连边,容量为p,将所有点i + N向T连边,然后对于每一对和为质数的点i,j,从i - j + N连边,容量为INF
最后整张图最大流的一半就是不得不放弃的最小权值,将总权值减去他和K比较即可check成功
#include <map> #include <set> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <bitset> #include <cstdio> #include <cstdlib> #include <cstring> #include <sstream> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define For(i, x, y) for(int i=x;i<=y;i++) #define _For(i, x, y) for(int i=x;i>=y;i--) #define Mem(f, x) memset(f,x,sizeof(f)) #define Sca(x) scanf("%d", &x) #define Sca2(x,y) scanf("%d%d",&x,&y) #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define Scl(x) scanf("%lld",&x) #define Pri(x) printf("%d\n", x) #define Prl(x) printf("%lld\n",x) #define CLR(u) for(int i=0;i<=N;i++)u[i].clear(); #define LL long long #define ULL unsigned long long #define mp make_pair #define PII pair<int,int> #define PIL pair<int,long long> #define PLL pair<long long,long long> #define pb push_back #define fi first #define se second typedef vector<int> VI; int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();} while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;} const double eps = 1e-9; const int maxn = 1010; const int maxm = 2e5 + 10; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; int N,M,K; bool isprime[maxm]; void init(){ for(int i = 2; i < maxm; i ++) isprime[i] = 1; for(int i = 2; i < maxm; i ++){ if(!isprime[i]) continue; for(int j = i + i; j < maxm; j += i){ isprime[j] = 0; } } } struct Dinic{ struct Edge{ int from,to,next,cap,flow; Edge(){} Edge(int from,int to,int next,int cap,int flow):from(from),to(to),next(next),cap(cap),flow(flow){} }edge[maxm * 2]; int n,s,t,head[maxn],tot; int dep[maxn],cur[maxn]; void init(int n,int s,int t){ this->n = n; this->s = s; this->t = t; tot = 0; for(int i = 0 ; i <= n ; i ++) head[i] = -1; } inline void add(int s,int t,int w){ //cout << s << ' ' << t << " " << w << endl; edge[tot] = Edge(s,t,head[s],w,0); head[s] = tot++; edge[tot] = Edge(t,s,head[t],0,0); head[t] = tot++; } inline bool BFS(){ for(int i = 0 ; i <= n ; i ++) dep[i] = -1; dep[s] = 1; queue<int>Q; Q.push(s); while(!Q.empty()){ int u = Q.front(); Q.pop(); for(int i = head[u]; ~i ; i = edge[i].next){ int v = edge[i].to; if(~dep[v] || edge[i].flow >= edge[i].cap) continue; dep[v] = dep[u] + 1; Q.push(v); } } return ~dep[t]; } inline int DFS(const int& u,int a){ if(u == t || !a) return a; int flow = 0; for(int &i = cur[u]; ~i ; i = edge[i].next){ int v = edge[i].to; if(dep[v] != dep[u] + 1) continue; int f = DFS(v,min(a,edge[i].cap - edge[i].flow)); if(!f) continue; edge[i ^ 1].flow -= f; edge[i].flow += f; a -= f; flow += f; } return flow; } inline int maxflow(){ return maxflow(s,t); } inline int maxflow(int s,int t){ int flow = 0; while(BFS()){ for(int i = 0; i <= n ; i ++) cur[i] = head[i]; flow += DFS(s,INF); } return flow; } }g; struct Node{ int p,c,l; }node[110]; bool cmp(Node a,Node b){ return a.l < b.l; } bool check(int m){ int S = N + N + 1,T = N + N + 2; g.init(T,S,T); LL sum = 0; // if(m == 4){ // puts("bug"); // } for(int i = 1; i <= N ; i ++){ if(node[i].l > m) break; sum += node[i].p * 2; g.add(S,i,node[i].p); g.add(i + N,T,node[i].p); for(int j = 1; j <= N ; j ++){ if(i == j) continue; if(node[j].l > m) break; if(isprime[node[i].c + node[j].c]) g.add(i,j + N,INF); } } int x = g.maxflow(); return (sum - x) >= M * 2; } int solve(){ int l = 1,r = N; int ans = -1; while(l <= r){ int m = l + r >> 1; if(check(m)){ ans = m; r = m - 1; }else{ l = m + 1; } } return ans; } int main(){ Sca2(N,M); init(); for(int i = 1; i <= N ; i ++) Sca3(node[i].p,node[i].c,node[i].l); sort(node + 1,node + 1 + N,cmp); Pri(solve()); return 0; }
G.
dp[i]表示到这个[1 - i]范围内的字符串A最多可以匹配多少B,dp2[i]表示最后一个字符串是以i结尾的情况下,[1-i]范围内的字符串最多可以匹配多少B
那么先通过跳next指针的方式更新dp[2],然后dp[i] = max(dp[i - 1],dp2[i])
#include <map> #include <set> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <bitset> #include <cstdio> #include <cstdlib> #include <cstring> #include <sstream> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define For(i, x, y) for(int i=x;i<=y;i++) #define _For(i, x, y) for(int i=x;i>=y;i--) #define Mem(f, x) memset(f,x,sizeof(f)) #define Sca(x) scanf("%d", &x) #define Sca2(x,y) scanf("%d%d",&x,&y) #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define Scl(x) scanf("%lld",&x) #define Pri(x) printf("%d\n", x) #define Prl(x) printf("%lld\n",x) #define CLR(u) for(int i=0;i<=N;i++)u[i].clear(); #define LL long long #define ULL unsigned long long #define mp make_pair #define PII pair<int,int> #define PIL pair<int,long long> #define PLL pair<long long,long long> #define pb push_back #define fi first #define se second typedef vector<int> VI; int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();} while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;} const double eps = 1e-9; const int maxn = 1e5 + 10; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; char A[maxn],B[maxn]; LL dp[maxn],dp2[maxn]; int nxt[maxn]; int N,M,K; void kmp_pre(char x[],int m,int nxt[]){ int j = 0; nxt[1] = 0; for(int i = 2; i <= m ; i ++){ while(j && x[i] != x[j + 1]) j = nxt[j]; if(x[j + 1] == x[i]) j ++; nxt[i] = j; } } int main(){ scanf("%s%s",A + 1,B + 1); N = strlen(A + 1),M = strlen(B + 1); kmp_pre(B,M,nxt); // for(int i = 1; i <= M ; i ++){ // cout << nxt[i] << " "; // } // cout << endl; for(int i = M; i <= N ; i ++){ bool flag = 1; for(int j = 1; j <= M; j ++){ if(B[j] != A[i - M + j] && A[i - M + j] != '?') flag = 0; } if(!flag){ dp[i] = dp[i - 1]; continue; } dp2[i] = max(dp2[i],dp[i - M] + 1); for(int j = nxt[M]; j ; j = nxt[j]){ dp2[i] = max(dp2[i],dp2[i - M + j] + 1); } dp[i] = max(dp[i - 1],dp2[i]); } Prl(dp[N]); return 0; }