codeforces div 313
C题
思路:补全三角形之后 减去三个角的个数和
锁了代码一看人家,就写了三行。。
公式: (f + a + b)^2 - b^2 - f^2 - d^2
D题
忧伤。。本来觉得直接递归模拟会T,结果姿势正确还可以过。。
标程思路:化成字典序最小的串然后比较。。
1 /*Author :usedrose */ 2 /*Created Time :2015/7/23 8:02:58*/ 3 /*File Name :2.cpp*/ 4 #include <cstdio> 5 #include <iostream> 6 #include <algorithm> 7 #include <sstream> 8 #include <cstdlib> 9 #include <cstring> 10 #include <climits> 11 #include <vector> 12 #include <string> 13 #include <ctime> 14 #include <cmath> 15 #include <deque> 16 #include <queue> 17 #include <stack> 18 #include <set> 19 #include <map> 20 #define INF 0x3f3f3f3f 21 #define eps 1e-8 22 #define pi acos(-1.0) 23 #define MAXN 1110 24 #define OK cout << "ok" << endl; 25 #define o(a) cout << #a << " = " << a << endl 26 #define o1(a,b) cout << #a << " = " << a << " " << #b << " = " << b << endl 27 using namespace std; 28 typedef long long LL; 29 30 string smallest(string s) { 31 if (s.length() % 2 == 1) return s; 32 string s1 = smallest(s.substr(0, s.length()/2)); 33 string s2 = smallest(s.substr(s.length()/2, s.length())); 34 if (s1 < s2) return s1 + s2; 35 else return s2 + s1; 36 } 37 38 int main() 39 { 40 //freopen("data.in","r",stdin); 41 //freopen("data.out","w",stdout); 42 cin.tie(0); 43 ios::sync_with_stdio(false); 44 string a, b; 45 cin >> a >> b; 46 a = smallest(a); 47 b = smallest(b); 48 if (a == b) cout <<"YES" << endl; 49 else cout << "NO" << endl; 50 return 0; 51 }
E题
题意:从h*w的格子, 从左上角(1,1)走到右下角(h, w),要求不能经过给出的几个黑格子,求有多少种可能。
组合数+逆元搞一下。。
这个 %= , +=, 真是6。。。
1 /*Author :usedrose */ 2 /*Created Time :2015/7/23 9:08:32*/ 3 /*File Name :2.cpp*/ 4 #include <cstdio> 5 #include <iostream> 6 #include <algorithm> 7 #include <sstream> 8 #include <cstdlib> 9 #include <cstring> 10 #include <climits> 11 #include <vector> 12 #include <string> 13 #include <ctime> 14 #include <cmath> 15 #include <deque> 16 #include <queue> 17 #include <stack> 18 #include <set> 19 #include <map> 20 #define INF 0x3f3f3f3f 21 #define eps 1e-8 22 #define pi acos(-1.0) 23 #define MAXH 200010 24 #define MAXN 2010 25 #define OK cout << "ok" << endl; 26 #define o(a) cout << #a << " = " << a << endl 27 #define o1(a,b) cout << #a << " = " << a << " " << #b << " = " << b << endl 28 using namespace std; 29 typedef long long LL; 30 const int mod = 1e9 + 7; 31 32 struct Point { 33 int x, y; 34 bool operator<(const Point &ss) & { 35 return x + y < ss.x + ss.y; 36 } 37 }p[MAXN]; 38 LL fac[MAXH], inv[MAXH]; 39 LL f[MAXN]; 40 41 inline LL FastPow(LL a, LL b) 42 { 43 LL res = 1; 44 while (b) { 45 if (b&1) (res *= a) %= mod; 46 (a *= a) %= mod; 47 b >>= 1; 48 } 49 return res; 50 } 51 52 LL Calc(int a, int b) 53 { 54 return (((fac[a+b-2]*inv[a-1])%mod)*inv[b-1])%mod; 55 } 56 int h, w, n, mx; 57 58 int main() 59 { 60 //freopen("data.in","r",stdin); 61 //freopen("data.out","w",stdout); 62 cin.tie(0); 63 ios::sync_with_stdio(false); 64 cin >> h >> w >> n; 65 for (int i = 1;i <= n; ++ i) 66 cin >> p[i].x >> p[i].y; 67 p[++n] = (Point){h, w}; 68 mx = h + w; 69 sort(p+1, p + 1 + n); 70 fac[0] = inv[0] = 1; 71 for (int i = 1;i <= mx; ++ i) 72 fac[i] = (fac[i-1]*(LL)i)% mod; 73 for (int i = 1;i <= mx; ++ i) 74 inv[i] = FastPow(fac[i], mod-2); 75 76 for (int i = 1;i <= n; ++ i) { 77 f[i] = Calc(p[i].x, p[i].y); 78 for (int j = 1;j < i; ++ j) 79 if (p[j].x <= p[i].x && p[j].y <= p[i].y) 80 { 81 f[i] -= f[j]*Calc(p[i].x - p[j].x + 1, p[i].y - p[j].y + 1)%mod; 82 ((f[i] %= mod) += mod) %= mod; 83 } 84 } 85 cout << f[n] << endl; 86 return 0; 87 }
附:
求 a / b = x (mod M)
只要 M 是一个素数,而且 b 不是 M 的倍数,就可以用一个逆元整数 b’,通过 a / b = a * b' (mod M)
,来以乘换除。
费马小定理说,对于素数 M 任意不是 M 的倍数的 b,都有:
b ^ (M-1) = 1 (mod M)
于是可以拆成:
b * b ^ (M-2) = 1 (mod M)
于是:
a / b = a / b * (b * b ^ (M-2)) = a * (b ^ (M-2)) (mod M)
也就是说我们要求的逆元就是 b ^ (M-2) (mod M)
!