【20180922】noip模拟赛
三道水题……T2差一步就做出来了……
第一题
每次考试都会发现第一题不会做然后去做后面的题之后闲得无聊做了做第一题才发现还是很水的
直接入手的话大概会很棘手,没法做,大胆猜想一下一定是从某个高度往下尽可能的走直到走到地面或者没钱了为止(从下往上走同理,由于这是一个逆操作所以可以合并)
也就是说要证明:不会出现往下走一段再往上走一段
这个十分显然,只需要考虑交换相邻两个高度不一样的楼房之后的代价区别就行了
然后只需要按照高度排序,然后枚举左端点,然后枚举右端点,然后强行选定这两个端点作为起始点和终点,然后对于之间的点按照$c$排序之后从小到大能选就选
于是就做完了……
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N = 60; 5 int n; ll T; 6 struct P { ll c, h; } p[N]; 7 bool operator < (P a, P b) { 8 if(a.h == b.h) return a.c < b.c; 9 else return a.h > b.h; 10 } 11 12 int main() { 13 freopen("meet.in", "r", stdin); 14 freopen("meet.out", "w", stdout); 15 scanf("%d", &n); 16 for(int i = 1 ; i <= n ; ++ i) scanf("%lld", &p[i].c); 17 for(int i = 1 ; i <= n ; ++ i) scanf("%lld", &p[i].h); 18 sort(p + 1, p + 1 + n); 19 scanf("%lld", &T); 20 int ans = 0; 21 for(int i = 1 ; i <= n ; ++ i) 22 if(p[i].c <= T) { 23 ans = 1; 24 break; 25 } 26 for(int i = 1 ; i <= n ; ++ i) { 27 for(int j = i + 1 ; j <= n ; ++ j) { 28 29 int lst = j; 30 while(lst - 1 >= i + 1 && p[lst - 1].h == p[j].h) -- lst; 31 swap(p[lst], p[j]); 32 33 ll t = T - (p[i].h - p[j].h) - p[i].c - p[j].c; 34 35 if(t >= 0) { 36 int res = 2; 37 38 // [i + 1, j - 1] 39 vector<ll> v; 40 for(int k = i + 1 ; k <= j - 1 ; ++ k) v.push_back(p[k].c); 41 if(v.size()) { 42 sort(v.begin(), v.end()); 43 for(int k = 0 ; k < v.size() ; ++ k) { 44 if(t - v[k] >= 0) { 45 ++ res; 46 t -= v[k]; 47 } else break; 48 } 49 } 50 // printf("[%d, %d], res = %d\n", i, j, res); 51 52 ans = max(ans, res); 53 } 54 55 swap(p[lst], p[j]); 56 } 57 } 58 printf("%d\n", ans); 59 }
第二题
第一眼感觉不可做……再想想发现还是很水的……
首先要求的这些数是不降的(因为让你这么输出的)
也就是说按照$a$升序排序之后,前两个数字之和是$a_1$,第一个数字和第三个数字之和是$a_2$,但并不知道$a_3$是谁
这时候只需要知道第二个和第三个数字的和是多少就行了,不妨暴力枚举它们的和
也就是说现在知道了
$$\begin{cases} x_1+x_2=a_1 \\ x_1+x_3=a_2 \\ x_2+x_3=a_t \end{cases}$$
解方程得:$x_1=\frac{a_1+a_2-a_t}{2}$
于是可以剪枝一下:$x_1$是非负整数
如果知道$x_1$,就可以直接依次递推出$x_n$了
1 // luogu-judger-enable-o2 2 #pragma GCC optimize(2) 3 #pragma GCC optimize(3) 4 #pragma GCC optimize("Ofast") 5 %:pragma GCC optimize("Ofast") 6 %:pragma GCC optimize("inline") 7 %:pragma GCC optimize("-fgcse") 8 %:pragma GCC optimize("-fgcse-lm") 9 %:pragma GCC optimize("-fipa-sra") 10 %:pragma GCC optimize("-ftree-pre") 11 %:pragma GCC optimize("-ftree-vrp") 12 %:pragma GCC optimize("-fpeephole2") 13 %:pragma GCC optimize("-ffast-math") 14 %:pragma GCC optimize("-fsched-spec") 15 %:pragma GCC optimize("unroll-loops") 16 %:pragma GCC optimize("-falign-jumps") 17 %:pragma GCC optimize("-falign-loops") 18 %:pragma GCC optimize("-falign-labels") 19 %:pragma GCC optimize("-fdevirtualize") 20 %:pragma GCC optimize("-fcaller-saves") 21 %:pragma GCC optimize("-fcrossjumping") 22 %:pragma GCC optimize("-fthread-jumps") 23 %:pragma GCC optimize("-funroll-loops") 24 %:pragma GCC optimize("-fwhole-program") 25 %:pragma GCC optimize("-freorder-blocks") 26 %:pragma GCC optimize("-fschedule-insns") 27 %:pragma GCC optimize("inline-functions") 28 %:pragma GCC optimize("-ftree-tail-merge") 29 %:pragma GCC optimize("-fschedule-insns2") 30 %:pragma GCC optimize("-fstrict-aliasing") 31 %:pragma GCC optimize("-fstrict-overflow") 32 %:pragma GCC optimize("-falign-functions") 33 %:pragma GCC optimize("-fcse-skip-blocks") 34 %:pragma GCC optimize("-fcse-follow-jumps") 35 %:pragma GCC optimize("-fsched-interblock") 36 %:pragma GCC optimize("-fpartial-inlining") 37 %:pragma GCC optimize("no-stack-protector") 38 %:pragma GCC optimize("-freorder-functions") 39 %:pragma GCC optimize("-findirect-inlining") 40 %:pragma GCC optimize("-fhoist-adjacent-loads") 41 %:pragma GCC optimize("-frerun-cse-after-loop") 42 %:pragma GCC optimize("inline-small-functions") 43 %:pragma GCC optimize("-finline-small-functions") 44 %:pragma GCC optimize("-ftree-switch-conversion") 45 %:pragma GCC optimize("-foptimize-sibling-calls") 46 %:pragma GCC optimize("-fexpensive-optimizations") 47 %:pragma GCC optimize("-funsafe-loop-optimizations") 48 %:pragma GCC optimize("inline-functions-called-once") 49 %:pragma GCC optimize("-fdelete-null-pointer-checks") 50 #include <bits/stdc++.h> 51 #include <unordered_map> 52 using namespace std; 53 typedef long long ll; 54 const int N = 310; 55 int n; ll a[N * N]; 56 struct FastIO { 57 static const int S = 1e7; 58 int wpos; 59 char wbuf[S]; 60 FastIO() : wpos(0) {} 61 inline int xchar() { 62 static char buf[S]; 63 static int len = 0, pos = 0; 64 if (pos == len) 65 pos = 0, len = fread(buf, 1, S, stdin); 66 if (pos == len) exit(0); 67 return buf[pos++]; 68 } 69 inline int operator () () { 70 int c = xchar(), x = 0; 71 while (c <= 32) c = xchar(); 72 for (; '0' <= c && c <= '9'; c = xchar()) x = x * 10 + c - '0'; 73 return x; 74 } 75 inline ll operator ! () { 76 int c = xchar(); ll x = 0; 77 while (c <= 32) c = xchar(); 78 for (; '0' <= c && c <= '9'; c = xchar()) x = x * 10 + c - '0'; 79 return x; 80 } 81 inline void wchar(int x) { 82 if (wpos == S) fwrite(wbuf, 1, S, stdout), wpos = 0; 83 wbuf[wpos++] = x; 84 } 85 inline void operator () (ll x) { 86 if (x < 0) wchar('-'), x = -x; 87 char s[24]; 88 int n = 0; 89 while (x || !n) s[n++] = '0' + x % 10, x /= 10; 90 while (n--) wchar(s[n]); 91 wchar('\n'); 92 } 93 inline void space(ll x) { 94 if (x < 0) wchar('-'), x = -x; 95 char s[24]; 96 int n = 0; 97 while (x || !n) s[n++] = '0' + x % 10, x /= 10; 98 while (n--) wchar(s[n]); 99 wchar(' '); 100 } 101 inline void nextline() { 102 wchar('\n'); 103 } 104 ~FastIO() 105 { 106 if (wpos) fwrite(wbuf, 1, wpos, stdout), wpos = 0; 107 } 108 } io; 109 110 ll num[N]; vector<vector<ll> > out; int cnt[N * N]; unordered_map<ll, int> tra; 111 ll ans[310][310]; int T; 112 113 void get() { 114 int q = 1; cnt[0] = 0; 115 for(int i = 1 ; i <= n * (n - 1) / 2 ; ++ i) cnt[tra[a[i]]] = 0; 116 for(int i = 1 ; i <= n * (n - 1) / 2 ; ++ i) ++ cnt[tra[a[i]]]; 117 for(int i = 2 ; i <= n ; ++ i) { 118 while(!cnt[tra[a[q]]]) ++ q; 119 num[i] = a[q] - num[1]; 120 for(int j = 1 ; j < i ; ++ j) 121 if(-- cnt[tra[num[j] + num[i]]] < 0) 122 return ; 123 } 124 ++ T; for(int i = 1 ; i <= n ; ++ i) ans[T][i] = num[i]; 125 } 126 127 int main() { 128 freopen("city.in", "r", stdin); 129 freopen("city.out", "w", stdout); 130 n = io(); for(int i = 1 ; i <= n * (n - 1) / 2 ; ++ i) a[i] = !io; 131 sort(a + 1, a + 1 + n * (n - 1) / 2); 132 tra[0] = 0; for(int i = 1, tot = 0 ; i <= n * (n - 1) / 2 ; ++ i) tra[a[i]] = ++ tot; 133 134 unordered_map<ll, int> vis; 135 for(int i = 3 ; i <= n ; ++ i) { 136 num[1] = (a[1] + a[2] - a[i]); 137 if(num[1] <= 0) break; 138 if((num[1] & 1) || vis[num[1] /= 2]) continue; 139 vis[num[1]] = 1, get(); 140 } 141 142 io(T); 143 for(int t = 1 ; t <= T ; ++ t, io.nextline()) 144 for(int i = 1 ; i <= n ; ++ i) 145 io.space(ans[T][i]); 146 io.nextline(); 147 }
第三题
开场先看的这题……数据结构的话应该很可做?(flag)
“模$p$等于$v$”——似曾相识啊,这怕不是洛谷 P3396 哈希冲突
由于数值不超过$10^4$,也就是说对于$p \gt 10^4$实际上是没用的,相当于查询值为$v$的个数,对于每一个数字把出现的下标扔到$vector$中暴力二分就行了
之后就是处理$p \le 10^4$的情况了,考虑按照$sqrt{10^4}$的大小分类讨论
如果$p \le 100$,那么可以预处理一堆$vector$,既$f_{i,j}$表示模$i$等于$j$的下标的集合,其中$1 \le i \le 100$,这样可以$O(10^7)$预处理,然后$O(\log n)$的查询了
如果$p \gt 100$,那么可以暴力去查找$v,v+p,v+2p,v+3p, \dots ,v+kp$,这大约只会执行$100$次
然后就可过了……
当然有更优秀的离线算法……
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 struct FastIO { 5 static const int S = 1e7; 6 int wpos; 7 char wbuf[S]; 8 FastIO() : wpos(0) {} 9 inline int xchar() { 10 static char buf[S]; 11 static int len = 0, pos = 0; 12 if (pos == len) 13 pos = 0, len = fread(buf, 1, S, stdin); 14 if (pos == len) exit(0); 15 return buf[pos++]; 16 } 17 inline int operator () () { 18 int c = xchar(), x = 0; 19 while (c <= 32) c = xchar(); 20 for (; '0' <= c && c <= '9'; c = xchar()) x = x * 10 + c - '0'; 21 return x; 22 } 23 inline ll operator ! () { 24 int c = xchar(); ll x = 0; 25 while (c <= 32) c = xchar(); 26 for (; '0' <= c && c <= '9'; c = xchar()) x = x * 10 + c - '0'; 27 return x; 28 } 29 inline void wchar(int x) { 30 if (wpos == S) fwrite(wbuf, 1, S, stdout), wpos = 0; 31 wbuf[wpos++] = x; 32 } 33 inline void operator () (ll x) { 34 if (x < 0) wchar('-'), x = -x; 35 char s[24]; 36 int n = 0; 37 while (x || !n) s[n++] = '0' + x % 10, x /= 10; 38 while (n--) wchar(s[n]); 39 wchar('\n'); 40 } 41 ~FastIO() 42 { 43 if (wpos) fwrite(wbuf, 1, wpos, stdout), wpos = 0; 44 } 45 } io; 46 47 const int N = 1e5 + 10; 48 vector<int> pos[N]; int n, m, a[N]; 49 vector<int> np[110][110]; 50 51 int calc(vector<int> &v, int n) { 52 if(v.empty() || *v.begin() > n) return 0; 53 return upper_bound(v.begin(), v.end(), n) - v.begin(); 54 } 55 56 int main() { 57 freopen("light.in", "r", stdin); 58 freopen("light.out", "w", stdout); 59 60 n = io(), m = io(); 61 for(int i = 1 ; i <= n ; ++ i) { 62 a[i] = io(); 63 pos[a[i]].push_back(i); 64 for(int j = 1 ; j <= 100 ; ++ j) { 65 np[j][a[i] % j].push_back(i); 66 } 67 } 68 for(int i = 1, l, r, p, v ; i <= m ; ++ i) { 69 l = io(), r = io(), p = io(), v = io(); 70 if(p > 10000) { 71 io(calc(pos[v], r) - calc(pos[v], l - 1)); 72 } else if(p <= 100) { 73 io(calc(np[p][v], r) - calc(np[p][v], l - 1)); 74 } else { 75 int ans = 0; 76 for(int j = v ; j <= 10000 ; j += p) 77 ans += calc(pos[j], r) - calc(pos[j], l - 1); 78 io(ans); 79 } 80 } 81 }