NOIP多校联考7
来自世间,一对平凡的夫妻身旁;来自昨天,谁以青春赴万丈理想?
A.计算器(calc)
依然不知道为什么会错,但是先按正解改一下好了……
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 105; const ll mod = 1e9 + 7; const int INF = 0x7ffffff; int n, k, cnt[maxn], ma, mb, mc, md; ll Max; inline int read() { int x = 0, f = 1; char ch = getchar(); while(ch > '9' || ch < '0') { if(ch == '-') { f = -1; } ch = getchar(); } while(ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + (ch^48); ch = getchar(); } return x * f; } struct node { int id, a, b, c, d; bool operator < (const node &T) const { return id < T.id; } }p[maxn]; ll query(int a, int b, int c, int d) { return (ll)(100+a)*(100+b)*(100+c)*(100+d); } int main() { n = read(); k = read(); for(int i=1; i<=n; i++) { p[i].id = read(); p[i].a = read(); p[i].b = read(); p[i].c = read(); p[i].d = read(); cnt[p[i].id]++; } sort(p+1, p+1+n); for(int i=1; i<=k; i++) { cnt[i] += cnt[i-1]; } for(int i=1; i<=k; i++) { int ha = ma, hb = mb, hc = mc, hd = md; for(int j=cnt[i-1]+1; j<=cnt[i]; j++) { int a = ma+p[j].a, b = mb+p[j].b, c = mc+p[j].c, d = md+p[j].d; ll res = query(a, b, c, d); if(res > Max) { Max = res; ha = a; hb = b; hc = c; hd = d; } } ma = ha; mb = hb; mc = hc; md = hd; } printf("%lld", Max); return 0; }
感谢能指出以上代码问题的大佬***%%%
抄完正解依然觉得自己毫无问题&%¥#@无可救药了
update:感觉好像错在了每个部位都取最大值不一定构成整体最大值,也就是不能分步贪心。顺便说一下dfs里的优化:记录即将跳到的位置,也就是cnt=0的根本就不展开成搜索树,不这样做的话好像会TLE80或90(同学的经验)
***如果问题不是我想到的这个,依然期待可以收到找到以上代码问题的大佬的评论***
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 105; const ll mod = 1e9 + 7; const int INF = 0x7ffffff; int n, m, x, cnt[maxn], e[maxn][maxn][4], nxt[maxn]; ll ans; inline int read() { int x = 0, f = 1; char ch = getchar(); while(ch > '9' || ch < '0') { if(ch == '-') { f = -1; } ch = getchar(); } while(ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + (ch^48); ch = getchar(); } return x * f; } void dfs(int x, int a, int b, int c, int d) { if(x > m) { ll tmp = (ll)a*b*c*d; if(tmp > ans) ans = tmp; return; } int num = cnt[x]; if(!num) { dfs(nxt[x], a, b, c, d); return; } for(int i=1; i<=num; i++) { dfs(x+1, a+e[x][i][0], b+e[x][i][1], c+e[x][i][2], d+e[x][i][3]); } } int main() { //freopen("calc2.in", "r", stdin); n = read(); m = read(); while(n--) { x = read(); cnt[x]++; for(int j=0; j<4; j++) e[x][cnt[x]][j] = read(); } x = m + 1; for(int i=m; i>=1; i--) { nxt[i] = x; if(cnt[i]) x = i; } ans = 0; dfs(1, 100, 100, 100, 100); printf("%lld\n", ans); return 0; }
B.对称轴(symmetry)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 2e5 + 3; const ll mod = 1e9 + 7; const int INF = 0x7ffffff; int T, n, ans; double x_1, y_1; inline int read() { int x = 0, f = 1; char ch = getchar(); while(ch > '9' || ch < '0') { if(ch == '-') { f = -1; } ch = getchar(); } while(ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + (ch^48); ch = getchar(); } return x * f; } struct node { int x, y; }p[maxn]; double get_k(double x_1, double y_1, double x_2, double y_2) { if(x_1 == x_2) return 1.0*INF; if(y_1 == y_2) return 0.0; return (y_1-y_2) / (x_1-x_2); } bool check(int l, int r, int a, int b, int k) { while(l > a && r > b) { double x_3 = (p[l].x+p[r].x)/2.0, y_3 = (p[l].y+p[r].y)/2.0; double k2 = get_k(x_1, y_1, x_3, y_3); l--; r++; if(abs(k-k2) > 1e-6) return 0; } return 1; } bool check2(int l, int r, int k) { while(l < r) { double x_3 = (p[l].x+p[r].x)/2.0, y_3 = (p[l].y+p[r].y)/2.0; double k2 = get_k(x_1, y_1, x_3, y_3); l++; r--; if(abs(k-k2) > 1e-6) return 0; } return 1; } bool check3(int l, int r, int k) { while(l < r) { double x_3 = (p[l].x+p[r].x)/2.0, y_3 = (p[l].y+p[r].y)/2.0; double k2 = get_k(x_1, y_1, x_3, y_3); l++; r--; if(abs(k-k2) > 1e-6) return 0; } double x_3 = p[l].x, y_3 = p[l].y; double k2 = get_k(x_1, y_1, x_3, y_3); if(abs(k-k2) > 1e-6) return 0; return 1; } double get_len(double x_1, double y_1, double x_2, double y_2) { return (x_1-x_2)*(x_1-x_2)+(y_1-y_2)*(y_1-y_2); } int main() { T = read(); while(T--) { n = read(); ans = 0; for(int i=1; i<=n; i++) { p[i].x = read(); p[i].y = read(); p[n+i].x = p[i].x; p[n+i].y = p[i].y; } if(n & 1) { for(int i=1; i<=n/2; i++) { int j = i+n-1; int lmax = (i+j)>>1, rmin = lmax+1; x_1 = p[i].x, y_1 = p[i].y; int l = lmax, r = rmin; double x_2 = (p[l].x+p[r].x)/2.0, y_2 = (p[l].y+p[r].y)/2.0; if(get_len(x_1, y_1, p[l].x, p[l].y) != get_len(x_1, y_1, p[r].x, p[r].y)) { continue; } double k = get_k(x_1, y_1, x_2, y_2); l--; r++; if(check(l, r, i, i+n, k)) ans++; } } else { for(int i=1; i<=n/2; i++) { int j = i+n-1; int l = i, r = j; x_1 = (p[l].x+p[r].x)/2, y_1 = (p[l].y+p[r].y)/2; l++; r--; double x_2 = (p[l].x+p[r].x)/2.0, y_2 = (p[l].y+p[r].y)/2.0; double k = get_k(x_1, y_1, x_2, y_2); l++; r--;; if(check2(l, r, k)) ans++; } for(int i=1; i<=n/2; i++) { int j = i+n; int l = i, r = j; x_1 = p[l].x, y_1 = p[l].y; l++; r--; double x_2 = (p[l].x+p[r].x)/2.0, y_2 = (p[l].y+p[r].y)/2.0; if(get_len(x_1, y_1, p[l].x, p[l].y) != get_len(x_1, y_1, p[r].x, p[r].y)) { continue; } double k = get_k(x_1, y_1, x_2, y_2); l++; r--; if(check3(l, r, k)) ans++; } } printf("%d\n", ans); } return 0; }
就是直接枚举对称轴的直线斜率。。我也不知道我为什么心血来潮的想调它,就调了3个小时。。。
结果就是T3和T4没时间审题了。。。 有人能暴力出80分,有人暴力能AC,果然我是个蒟蒻。
至于正解:(一个图形旋转一个小于180°的角,能够和自己重合几次,就有几条对称轴)
好像上面那句话有点无关,不过似乎可以提供一些灵感,那就是依次记录多边形边的长度和角的大小,把这道题转化成字符串。因为变长带根号,角也不好求(据说算三角函数常数很大),就考虑一种简洁的记录方式——用边长的平方表示边长,用向量的叉积表示角度(这个正解想不出来不能怪我,叉积还没学呢,谁知道它还有这种用途!),实数环就变成了整数环,and then 问题就成了:环上有几个位置,满足环从这里断开后,可以得到一条回文链?
match数组记录这条实数环,为了枚举断点所以要两倍长度,pattern数组是这个实数环的“反环”(内容相同方向相反),用KMP算法不断将match和pattern进行字符串匹配,这就比较板子,可惜我忘了……
叉积公式(abcd什么的就是坐标表示的向量的坐标啊,居然还花了好几分钟理解这个式子):(a, b) × (c, d) = ad - bc
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 2e5 + 3; const ll mod = 1e9 + 7; const int INF = 0x7ffffff; #define sqr(x) ((x)*(x)) int T, n, tot, ans, x[maxn], y[maxn], pattern[maxn], match[maxn<<1]; int nxt[maxn<<1]; inline int read() { int x = 0, f = 1; char ch = getchar(); while(ch > '9' || ch < '0') { if(ch == '-') { f = -1; } ch = getchar(); } while(ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + (ch^48); ch = getchar(); } return x * f; } int main() { //freopen("sym2.in", "r", stdin); T = read(); while(T--) { n = read(); for(int i=1; i<=n; i++) { x[i] = read(); y[i] = read(); } x[n+1] = x[1], y[n+1] = y[1], x[n+2] = x[2], y[n+2] = y[2]; tot = 0; ans = 0; for(int i=1; i<=n; i++) { match[++tot] = sqr(x[i+1]-x[i])+sqr(y[i+1]-y[i]); match[++tot] = (x[i+1]-x[i])*(y[i+2]-y[i])-(y[i+1]-y[i])*(x[i+2]-x[i]); } for(int i=1; i<=tot; i++) { pattern[tot-i+1] = match[i+tot] = match[i]; } memset(nxt, 0, sizeof(nxt)); for(int i=2,j=0; i<=tot; i++) { while(j && pattern[j+1]!=pattern[i]) j = nxt[j]; nxt[i] = (j+=(pattern[j+1]==pattern[i])); } for(int i=1,j=0; i<=(tot<<1); i++) { while(j && pattern[j+1]!=match[i]) j = nxt[j]; j += (pattern[j+1]==match[i]); if(j == tot) ans++, j=nxt[j]; } printf("%d\n", ans); } return 0; }
D.签到题(qiandao)
我没到,,或者说,,我迟到了
知道了规律是什么还要开一个vector TLE70,我对我自己真是无语了。。。分明是桶就能解决的问题
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 1e6 + 3; const ll mod = 1e9 + 7; const int INF = 0x7ffffff; int n, m, c, k, ans; int a[maxn]; inline int read() { int x = 0, f = 1; char ch = getchar(); while(ch > '9' || ch < '0') { if(ch == '-') { f = -1; } ch = getchar(); } while(ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + (ch^48); ch = getchar(); } return x * f; } int main() { //freopen("qiandao4.in", "r", stdin); n = read(); m = read(); k = read(); c = read(); for(int i=1; i<=k; i++) { int x = read(), y = read(); a[x]++; a[y+n]++; } for(int i=1; i<=n+m; i++) { if(a[i]%c) ans++; } printf("%d\n", ans); return 0; }