A.t == 10的时候输出1后面跟n - 1个0,否则输出n个t
#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 ", x) #define Prl(x) printf("%lld ",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; int main(){ Sca2(N,M); if(M == 10){ if(N == 1) puts("-1"); else{ printf("1"); for(int i = 0 ; i < N - 1; i ++) printf("0"); } return 0; } for(int i = 1; i <= N; i ++) printf("%d",M); return 0; }
B.枚举每一个二进制中只含一个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 ", x) #define Prl(x) printf("%lld ",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; string t; bitset<70>Q[70]; int main(){ ULL l,r;cin >> l >> r; LL ans = 0; for(int i = 0 ; i < 63; i ++){ for(int j = 0; j < i; j ++){ Q[i][j] = 1; } for(int j = 0 ; j < i - 1; j ++){ Q[i][j] = 0; ULL sum = Q[i].to_ullong(); if(l <= sum && sum <= r){ ans++; } Q[i][j] = 1; } } Prl(ans); return 0; }
C.每个点只能向右扩展或者向下扩展,分别维护出向右向下扩展的二维前缀和。
计算的时候调整边界,容斥出答案为dp[x2][y2] - dp[x2][y1 - 1] - dp[x1 - 1][y2] + dp[x1 - 1][y1 - 1]
#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 ", x) #define Prl(x) printf("%lld ",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 = 510; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; int N,M,K; char MAP[maxn][maxn]; LL dp[2][maxn][maxn]; int main(){ Sca2(N,M); for(int i = 1; i <= N ; i ++) scanf("%s",MAP[i] + 1); for(int i = 1; i <= N ; i ++){ for(int j = 1; j <= M; j ++){ if(MAP[i][j] == '#') continue; if(i != N && MAP[i + 1][j] == '.') dp[0][i][j]++; if(j != M && MAP[i][j + 1] == '.') dp[1][i][j]++; } } for(int i = 1; i <= N ; i ++){ for(int j = 1; j <= M ; j ++){ dp[1][i][j] = dp[1][i][j] + dp[1][i - 1][j] + dp[1][i][j - 1] - dp[1][i - 1][j - 1]; dp[0][i][j] = dp[0][i][j] + dp[0][i - 1][j] + dp[0][i][j - 1] - dp[0][i - 1][j - 1]; } } int Q; Sca(Q); while(Q--){ int x1,x2,y1,y2; Sca2(x1,y1); Sca2(x2,y2); x2--; LL ans = dp[0][x2][y2] - dp[0][x1 - 1][y2] - dp[0][x2][y1 - 1] + dp[0][x1 - 1][y1 - 1]; x2++; y2--; ans += dp[1][x2][y2] - dp[1][x1 - 1][y2] - dp[1][x2][y1 - 1] + dp[1][x1 - 1][y1 - 1]; Prl(ans); } return 0; }
D.dp[i][j]表示以i到j这段区间内结尾的数字的种数。
然后可以写出一个n ^ 4的dp(三层枚举一层比较),用EXKMP预处理出每两个位置之间的最长公共前缀优化掉一层比较。
用树状数组代替dp优化掉一层枚举,时间复杂度n2logn
补:赛后十分钟过题真刺激,因为开始贪图简便写了个BFS来dp,就不好优化了,以后能直接写的dp还是直接写
#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 ", x) #define Prl(x) printf("%lld ",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 = 5010; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; int N,M,K; char str[maxn]; LL dp[maxn][maxn]; void pre_EKMP(char x[],int m,int next[]){ next[0] = m; int j = 0; while(j + 1 < m && x[j] == x[j + 1]) j ++; next[1] = j; int k = 1; for(int i = 2; i < m ; i ++){ int p = next[k] + k - 1; int L = next[i - k]; if(i + L < p + 1) next[i] = L; else{ j = max(0,p - i + 1); while(i + j < m && x[i + j] == x[j]) j ++; next[i] = j; k = i; } } } int nxt[maxn][maxn]; bool cmp(int l1,int r1,int l2,int r2){ int len1 = r1 - l1 + 1,len2 = r2 - l2 + 1; if(len1 > len2) return 1; if(len1 < len2) return 0; int l = nxt[l2][l1]; if(l >= len1) return 0; // cout << l1 << " " << l2 << " " << str[l1 + l + 1] << " " << str[l2 + l + 1] << endl; return str[l1 + l] > str[l2 + l]; } LL tree[maxn][maxn]; void update(LL *tr,int t,LL p){ for(;t <= N ; t += t & -t) tr[t] = (tr[t] + p) % mod; } LL getsum(LL *tr,int p){ LL ans = 0; for(;p > 0; p -= p & -p) ans = (ans + tr[p]) % mod; return ans; } int main(){ Sca(N); scanf("%s",str + 1); for(int i = 1; i <= N ; i ++){ pre_EKMP(str + i,N - i + 1,nxt[i] + i); } update(tree[1],1,1); for(int i = 1; i <= N ; i ++){ if(str[i] == '0') continue; for(int j = 1; j < i ; j ++){ if(str[j] == '0') continue; int len = i - j; LL x = getsum(tree[j],i - 1); if(!x) continue; int r = i + len - 3; while(r <= N && !cmp(i,r,j,i - 1)) r++; //cout << j << " " << i - 1 <<"update" << i << " " << r << " " << endl; update(tree[i],r,x); } } LL ans = 0; for(int i = 1; i <= N ; i ++) ans = (ans + getsum(tree[i],N)) % mod; Prl(ans); return 0; }
E.将题目的难度从大到小排序,然后枚举
排序三人做题能力为c > b > a
每次遇到的当前最难的题按照先让c做,不行就让a + b做然后依次轮到a + c,b +c,a + b + c来做。
除了第一种情况,其余的都只存在一个人或没有人再空余,让那个人去做当前最难的他能做的题目。
第一种情况,如果b能单独切一道题就让a,b分开切,否则就让a,b合起来做题,用平衡树或multiset直接维护这个过程
#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 ", x) #define Prl(x) printf("%lld ",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; struct Node{ int a[4]; int num; Node(){} Node(int n,int A,int B = INF,int C = INF){ num = n; a[1] = A; a[2] = B; a[3] = C; } }node[100]; int a,b,c; int Hash[maxn * 2]; int x[maxn]; int cnt = 0; int tree[maxn]; void update(int t,int p){ for(;t > 0; t -= t & -t) tree[t] += p; } int getsum(int t){ int ans = 0; for(;t <= cnt;t += t & -t) ans += tree[t]; return ans; } multiset<int>Q; int main(){ Sca(N); cnt = 0; scanf("%d%d%d",&a,&b,&c); if(c < b) swap(c,b); if(b < a) swap(b,a); if(c < b) swap(c,b); for(int i = 1; i <= N; i ++){ Sca(x[i]); if(x[i] > a + b + c){ puts("-1"); return 0; } } for(int i = 1; i <= N ; i ++) Q.insert(x[i]); Q.insert(-INF); Q.insert(INF); node[1] = Node(3,c,b,a); node[2] = Node(2,a + b,c); node[3] = Node(2,a + c,b); node[4] = Node(2,c + b,a); node[5] = Node(1,a + b + c); int ans = 0; while(Q.size() > 2){ set<int>::iterator it = Q.end(); it--; it--; for(int i = 1; i <= 5; i ++){ if(node[i].a[1] < (*it)) continue; ans++; Q.erase(it); if(i == 1){ it = Q.upper_bound(node[i].a[2]); it--; if((*it) == -INF){ it = Q.upper_bound(b + a);it--; if((*it) != -INF) Q.erase(it); }else{ Q.erase(it); it = Q.upper_bound(node[i].a[3]); it--; if((*it) != -INF) Q.erase(it); } }else{ if(node[i].num == 2){ it = Q.upper_bound(node[i].a[2]); it--; if((*it) != -INF) Q.erase(it); } } break; } } Pri(ans); return 0; }
F.计算出一个指令下机器人到达的最上下左右端的距离,通过到达最远距离的时间点可以反推出每行每列的机器人撞墙的最早时间。
容易证明每行每列撞墙的时间波形呈周期性,周期长度是指令的长度len,每i + 1个周期相比于第i个周期的相同位置答案也要高len,因此只要算出每个周期的波形,就可以推出行列整个周期的波形
然后知道了每行每列的最早撞墙时间就好求解了,将其中一个数组排序之后求一个前缀和,另一个去二分他计算答案
#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 ", x) #define Prl(x) printf("%lld ",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 = 5e5 + 10; const LL INF = 3e18; const int mod = 1e9 + 7; int len,N,M,K; char str[maxn * 10]; LL w[maxn],h[maxn],pre[maxn]; int main(){ Sca3(len,N,M); for(int i = 1; i <= N ; i ++) h[i] = INF; for(int j = 1; j <= M ; j ++) w[j] = INF; int W = M,H = N; scanf("%s",str + 1); int l = 0,r = 0,d = 0,u = 0; int L = 0,R = 0,D = 0,U = 0; for(LL i = 1; str[i] && W && H; i ++){ // cout << U << " " << d << endl; if(str[i] == 'R'){r++;l--;} if(str[i] == 'L'){l++;r--;} if(str[i] == 'U'){u++;d--;} if(str[i] == 'D'){d++;u--;} if(l > L){L = l;if(w[L] == INF) W--;w[L] = min(w[L],i);} if(r > R && M >= R){R = r;if(w[M - R + 1] == INF) W--; w[M - R + 1] = min(w[M - R + 1],i);} if(u > U){U = u;if(h[U] == INF) H--; h[U] = min(h[U],i);} if(d > D && N >= D){D = d;if(h[N - D + 1] == INF) H--; h[N - D + 1] = min(h[N - D + 1],i);} } if(!l && !u && (W && H)){ puts("-1"); return 0; } if(l > 0){ for(int i = l + 1; i <= M; i ++) w[i] = min(w[i],w[i - l] + len); }else if(l < 0){ for(int i = M - r; i >= 1; i --) w[i] = min(w[i],w[i + r] + len); } if(u > 0){ for(int i = u + 1; i <= N; i ++) h[i] = min(h[i],h[i - u] + len); }else if(u < 0){ for(int i = N - d; i >= 1; i --) h[i] = min(h[i],h[i + d] + len); } // cout << w[1] << " " << w[2] << endl; int flag = 0; for(int i = 1; i <= N ; i ++) if(h[i] == INF) flag = 1; for(int j = 1; j <= M ; j ++) if(w[j] == INF && flag) {puts("-1");return 0;} sort(w + 1,w + 1 + M); LL sum = 0; for(int i = 1; i <= M ; i ++) pre[i] = (pre[i - 1] + w[i]) % mod; LL ans = 0; for(int i = 1; i <= N ; i ++){ int p = lower_bound(w + 1,w + 1 + M,h[i]) - w; ans = (ans + (pre[p - 1] + (M - p + 1) * h[i] % mod) % mod) % mod; } Prl(ans); return 0; }