Codeforces Round #313
A. Currency System in Geraldion
大水,没什么好说的。显然只要有1就能凑出所有数字,没有1就凑不出1,1就是那个最小的
B. Gerald is into Art
两个矩形能不能不重叠的放入第三个中。
暴力枚举一下放的方式
写的比较丑
#include <bits/stdc++.h> using namespace std; int a1, a2, a3, b1, b2, b3; bool check(){ if(max(a2, a3) <= a1 && b2 +b3<= b1) return true; if(a2 + a3 <= a1 && max(b2, b3) <= b1) return true; if(a2 + a3 <= b1 && max(b2, b3) <= a1)return true; if(max(a2, a3) <= b1 && b2 + b3 <= a1) return true; if(max(a2, b3) <= b1 && a3 + b2 <= a1) return true; if(max(a2, b3) <= a1 && a3 + b2 <= b1) return true; if(max(b2, a3) <= b1 && a2 + b3 <= a1) return true; if(max(b2, a3) <= a1 && a2 + b3 <= b1) return true; return false; } int main(){ cin >> a1 >>b1 >>a2 >>b2 >> a3 >> b3; if(a1 > b1) swap(a1, b1); if(a2 > b2) swap(a2, b2); if(a3 > b3) swap(a3, b3); printf("%s\n", check() ? "YES" : "NO"); return 0; }
C. Gerald's Hexagon
给一个每个角都是120度的六边形的周长,求面积。。
一开始十分脑残企图往里面缩。。。
然而。。。。。。。。。。。。。。
酱紫,因为每个角都是120度,所以所有外角是60度,往外可以搞出一个等边三角形,删去三个小的小的三角形,就是面积了
写到后来失去思考能力了直接写了个循环求和呵呵呵==
#include <bits/stdc++.h> using namespace std; typedef __int64 ll; int a[10]; const int n = 6; int main(){ ll ans = 0; int i, t; int x, y; bool ok; for(i = 0; i < n; i++){ cin >> a[i]; } t = a[1] + a[0] + a[5]; while(t){ ans += t * 2 - 1; t--; } // cout << ans << endl; for(i = 1; i < n; i+=2){ while(a[i]){ ans -= (a[i]*2-1); a[i]--; } } cout << ans << endl; return 0; }
D. Equivalent Strings
两个字符串Equivalent 的条件是满足以下之一
1.两个字符串完全相同
2.将他们等分成等长的两部分a1 a2 b1 b2,可使得(a1Equivalent to b1 and a2 Equivalent to b2) or (a1 Equivalent to b2 and a2 Equivalent to b1)
用了一点最小表示法的思想?
直接将两个重新排个序,看是否相等。
NICE!
#include <bits/stdc++.h> using namespace std; string a, b; string gao(string s){ if(s.length() & 1) return s; string s1 = gao(s.substr(0, s.length() / 2)); string s2 = gao(s.substr(s.length()/2, s.length())); if(s1 < s2) return s1 + s2; return s2 + s1; } int main(){ cin >> a >> b; a = gao(a); b = gao(b); printf("%s\n", a == b ? "YES" : "NO" ); return 0; }
E. Gerald and Giant Chess
一个Height*Width的图,(100000*100000),里面有不多于2000个黑点不能经过。每次只能往下走一格或者往右走一格,求从左上到右下的方案数。
DP状态设计的非常6,设dp[i]表示到达第i个黑点之前没有经过别的黑点的方案数。
不妨将终点看成一个黑点。。因为懒。
如果不考虑黑点的话,从起点到(x,y) 的方案数是C(x+y, x),高中数学姿势。
接下来考虑进黑点。 对于i(x, y) 原本的方案数是C(x+y, x),我们需要从中删除那些经过黑点的方案数。也许会经过好多个黑点,但反正都是不合法的,所以我们只用考虑第一个黑点是哪个。
于是枚举所有的黑点j(x',y'),如果它满足在(x, y)的左上角,那么他就是我们之前统计出的方案中需要删去的。从起点第一次到达(x'y')的方案数是dp[j],从j点到达i的方案数是C(p[i].x-p[j].x+p[i].y-p[j].y, p[i].x-p[j].x) 将他们相乘就是先到达j再到达i的方案数。
完事
#include <bits/stdc++.h> using namespace std; typedef __int64 ll; const int N = 2004; const int M = 200004; const int MOD = 1000000007; struct point{ int x, y; point(){}; point(int _x, int _y){x = _x, y = _y;}; void scan(){ scanf("%d%d", &x, &y); } bool operator<(const point &I)const{ if(x == I.x) return y < I.y; return x <I.x; } }p[N]; ll dp[N]; ll fac[M], inv[M]; ll quickpow(ll base, int p){ ll ans = 1; while(p){ if(p&1){ ans = ans * base % MOD; } base = base * base % MOD; p >>= 1; } return ans; } ll cal(int x, int y){ return fac[x+y]*inv[x]%MOD*inv[y]%MOD; } int main(){ int h, w, n, i, j, m; scanf("%d%d%d", &h, &w, &n); for(i = 1; i <= n; i++){ p[i].scan(); } p[++n] = point(h, w); sort(p + 1, p + n + 1); m = h + w; fac[0] = 1; inv[0] = 1; for(i = 1; i <= m; i++){ fac[i] = fac[i-1]*i%MOD; inv[i] = quickpow(fac[i], MOD-2); } for(i = 1; i <= n; i++){//printf("%I64d\n", dp[i]); dp[i] = cal(p[i].x-1, p[i].y-1); for(j = 1; j < i; j++){ if(p[j].y <= p[i].y){ dp[i] = ((dp[i] - dp[j]*cal(p[i].y-p[j].y, p[i].x-p[j].x)%MOD)%MOD + MOD) % MOD; } } } printf("%I64d\n", dp[n]); return 0; }