Codeforces #313 div1
2015-07-26 14:05:40
【传送门】
总结:前三题都是可做的。赛中三题,由于最近的多校,没补后面的题了... 第二题有点坑爹... hack 数据是针对某些 dfs 顺序的。用 string 的就可能被卡。
A题:简单题。将其补全成正三角形就 ok 了。
#include <cstdio> #include <ctime> #include <cstring> #include <cstdlib> #include <cmath> #include <vector> #include <map> #include <set> #include <stack> #include <queue> #include <string> #include <iostream> #include <algorithm> using namespace std; #define getmid(l,r) ((l) + ((r) - (l)) / 2) #define MP(a,b) make_pair(a,b) #define PB push_back typedef long long ll; typedef pair<int,int> pii; const double eps = 1e-8; const int INF = (1 << 30) - 1; int a,b,c,d,e,f; int main(){ scanf("%d%d%d%d%d%d",&a,&b,&c,&d,&e,&f); int D = e + d + c; int ans = D * D - a * a - e * e - c * c; printf("%d\n",ans); return 0; }
B题:根据题意模拟即可,注意 DFS 传的参数要少。
#include <cstdio> #include <ctime> #include <cstring> #include <cstdlib> #include <cmath> #include <vector> #include <map> #include <set> #include <stack> #include <queue> #include <string> #include <iostream> #include <algorithm> using namespace std; #define getmid(l,r) ((l) + ((r) - (l)) / 2) #define MP(a,b) make_pair(a,b) #define PB push_back typedef long long ll; typedef pair<int,int> pii; const double eps = 1e-8; const int INF = (1 << 30) - 1; const int MAXN = 200010; char s1[MAXN],s2[MAXN]; int len1,len2; bool Dfs(int a1,int b1,int a2,int b2){ if(a1 == b1){ return s1[a1] == s2[a2]; } if((b1 - a1 + 1) & 1){ for(int i = a1; i <= b1; ++i) if(s1[i] != s2[i - a1 + a2]) return false; return true; } int mid1 = (a1 + b1) >> 1,mid2 = (a2 + b2) >> 1; if(Dfs(a1,mid1,a2,mid2) && Dfs(mid1 + 1,b1,mid2 + 1,b2)) return true; if(Dfs(a1,mid1,mid2 + 1,b2) && Dfs(mid1 + 1,b1,a2,mid2)) return true; return false; } int main(){ scanf("%s%s",s1 + 1,s2 + 1); len1 = strlen(s1 + 1); len2 = strlen(s2 + 1); if(Dfs(1,len1,1,len2)){ printf("YES\n"); } else{ printf("NO\n"); } return 0; }
C题:组合数,DP
题意:从(1,1)走到(h,w)且不经过黑格子的走法数,只能向右 / 向下走,黑格子数<=2000。
思路:显然是根据黑格子来思考,由于不存在黑格子时从(1,1)到(n,m)的走法是C(n+m,n),所以可以这么考虑:
从最后一个黑格子(最靠近终点的黑格子)开始倒着考虑,DP[i] 表示从第 i 个黑格子出发不经过其他黑格子到终点的走法数,那么最后一个黑格子的 dp 就可以直接用组合数算出来,计算其他点的 dp 值时需要枚举最后经过哪个黑格子,比如考虑第 i 个黑格子,就要枚举第 i+1 <= j <= k 个黑格子作为最后经过的黑格子,那么 dp[i] = Sigma(cnt(i , j) * dp[j]),cnt(i , j) 表示从第 i 个黑格子到第 j 个黑格子的走法数。
最后的答案就是 Sigma(cnt(st , i) * dp[i])(1 <= i <= k),k 为黑格子数。
#include <cstdio> #include <ctime> #include <cstring> #include <cstdlib> #include <cmath> #include <vector> #include <map> #include <set> #include <stack> #include <queue> #include <string> #include <iostream> #include <algorithm> using namespace std; #define getmid(l,r) ((l) + ((r) - (l)) / 2) #define MP(a,b) make_pair(a,b) #define PB push_back typedef long long ll; typedef pair<int,int> pii; const double eps = 1e-8; const int INF = (1 << 30) - 1; const ll mod = 1e9 + 7; const int MAXN = 200000; ll fac[MAXN + 10],afac[MAXN + 10]; ll dp[2010][2010],res[2010]; int h,w,n; struct node{ int X,Y; }P[2010]; ll Q_pow(ll x,ll y){ x %= mod; ll res = 1; while(y){ if(y & 1) res = res * x % mod; x = x * x % mod; y >>= 1; } return res; } void Pre(){ fac[0] = afac[0] = 1; for(int i = 1; i <= MAXN; ++i) fac[i] = fac[i - 1] * (ll)i % mod; afac[MAXN] = Q_pow(fac[MAXN],mod - 2); for(int i = MAXN; i >= 1; --i) afac[i - 1] = afac[i] * i % mod; } ll C(int n,int m){ if(m == 0 || m == n) return 1; return fac[n] * afac[n - m] % mod * afac[m] % mod; } bool cmp(node a,node b){ if(a.X == b.X) return a.Y > b.Y; return a.X > b.X; } int main(){ Pre(); scanf("%d%d%d",&h,&w,&n); for(int i = 1; i <= n; ++i){ scanf("%d%d",&P[i].X,&P[i].Y); } sort(P + 1,P + n + 1,cmp); ll ans = C(h + w - 2,h - 1); for(int i = 1; i <= n; ++i){ //从这个点到终点 int a1 = h - P[i].X + w - P[i].Y; int a2 = h - P[i].X; res[i] = C(a1,a2); for(int j = 1; j < i; ++j){ a1 = P[j].X - P[i].X + P[j].Y - P[i].Y; a2 = P[j].X - P[i].X; res[i] = (res[i] - C(a1,a2) * res[j] % mod + mod) % mod; } } for(int i = 1; i <= n; ++i){ int a1 = P[i].X - 1 + P[i].Y - 1; int a2 = P[i].X - 1; ans = (ans - C(a1,a2) * res[i] % mod + mod) % mod; } printf("%I64d\n",ans); return 0; }