码迷,mamicode.com
首页 > 其他好文 > 详细

BestCoder Round #40

时间:2016-05-19 23:18:26      阅读:265      评论:0      收藏:0      [点我收藏+]

标签:

弱渣做不动CF了,弱渣只能水水BC了,于是就开始每周开心地BC了,顺便写个水水的题解~~

 

题A hdu 5224

题意:略

题解:枚举边长即可。

 

技术分享
 1 /*zhen hao*/
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 
 5 #define lson l, m, rt*2
 6 #define rson m + 1, r, rt*2+1
 7 #define xx first
 8 #define yy second
 9 
10 typedef pair<int,int> pii;
11 typedef long long ll;
12 typedef unsigned long long ull;
13 
14 int main() {
15 //  freopen("case.in", "r", stdin);
16   int T;
17   cin >> T;
18   while (T--) {
19     int n;
20     scanf("%d", &n);
21     int ans = 1 << 30;
22     for (int i = 1; i * i <= n; i++) {
23       if (n % i == 0) {
24         ans = min(ans, 2 * (i + n / i));
25       }
26     }
27     printf("%d\n", ans);
28   }
29   return 0;
30 }
代码君

 

题B hdu 5225

题意:略

题解:可以用递推算出每个大小为n的排列的逆序对总数,就是考虑每次增加n之后逆序对数增加多少,分别把n放在第一个位置……第n个位置。得到s[n];然后就是对于一个排列运用类似的方法,不断细化,想数位dp得到答案的过程一样。具体是这样,我也不知道怎么水出来的~~

 

技术分享
 1 /*zhen hao*/
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 
 5 #define lson l, m, rt*2
 6 #define rson m + 1, r, rt*2+1
 7 #define xx first
 8 #define yy second
 9 
10 typedef pair<int,int> pii;
11 typedef long long ll;
12 typedef unsigned long long ull;
13 
14 const int mod = 1e9 + 7, maxn = 1e2 + 10;
15 int p[maxn], vis[maxn], n;
16 ll s[maxn], f[maxn];
17 
18 void init() {
19   f[1] = 1; s[1] = 0;
20   for (int i = 2; i < maxn; i++) {
21     f[i] = f[i - 1] * i % mod;
22     s[i] = (s[i - 1] * i % mod + f[i - 1] * i * (i - 1) / 2) % mod;
23   }
24 //  cout << s[5] << endl;
25 }
26 
27 ll slove() {
28   ll ret = 0;
29   memset(vis, 0, sizeof vis);
30   ll big = 0;
31   for (int i = 1; i <= n; i++) {
32     for (int j = 1; j < p[i]; j++) if (!vis[j]) {
33       ll extra = 0;
34       for (int k = 1; k < j; k++) if (!vis[k]) extra++;
35       ret += ((big + extra) * f[n - i] + s[n - i]) % mod;
36       if (ret >= mod) ret -= mod;
37     }
38     for (int j = 1; j < p[i]; j++) if (!vis[j]) big++;
39     vis[p[i]] = 1;
40   }
41   return ret;
42 }
43 
44 int main() {
45 //  freopen("case.in", "r", stdin);
46   init();
47   while (scanf("%d", &n) == 1) {
48     for (int i = 1; i <= n; i++) scanf("%d", p + i);
49     printf("%I64d\n", slove());
50   }
51   return 0;
52 }
代码君

 

题C hdu 5226

题意:略

题解:先说一下我的做法,对于一个组合数可以写成c(a, b) = c(a - 1, b - 1) + c(a - 1, b),所以上一行是下一行乘以2再减去最右端的(只加了一次),所以可以递推过去。然后就是这道题的一个坑点:不能直接求逆元。为什么呢?因为假设分子的p因子的个数更多,那么modp之后得到的就是0,所以这时候求逆元就不准了,究其原因就是因为gcd!=1,所以不能够求逆元,除去这种情况是可以的,因为p是素数。解决方法有两种:

1、lucas定理,因为是以p为一次划分,所以可以很有效地避免。

2、要求a!/ (b ! * (a - b)!),所以求出num[a]表示a!有多少个p,然后只要num[a] - num[b] - num[a - b] > 0就直接是0,其余就可以用逆元来处理。

 

最后官方并不需要我那样递推过去,而是用一个性质:C(x + 1,y)即为∑x C(i,y),具体可以联系杨辉三角来证。

 

技术分享
 1 /*zhen hao*/
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 
 5 #define lson l, m, rt*2
 6 #define rson m + 1, r, rt*2+1
 7 #define xx first
 8 #define yy second
 9 
10 typedef pair<int,int> pii;
11 typedef long long ll;
12 typedef unsigned long long ull;
13 
14 const int maxn = 2e5 + 10;
15 ll p;
16 ll f[maxn], c[maxn];
17 
18 ll quick(ll a, ll b) {
19   ll ret = 1;
20   while (b > 0) {
21     if (b & 1) ret = ret * a % p;
22     a = a * a % p;
23     b = b / 2;
24   }
25   return ret;
26 }
27 
28 void init() {
29   f[0] = 1;
30   for (int i = 1; i < maxn; i++) f[i] = f[i - 1] * i % p;
31   for (int i = 0; i < maxn; i++) c[i] = quick(f[i], p - 2);
32 }
33 
34 ll C(int n, int m) {
35   if(n == 0 && m == 0) return 1;
36   if(n == 0) return 0;
37   if(n % p < m % p) return 0;
38   int x = n % p, y = m % p;
39   return f[x] * c[y] % p * c[x-y] % p * C(n / p, m / p);
40 }
41 
42 ll slove(int x, int y) {
43   if (x < 0 || y < 0) return 0;
44   ll ret = 1  , s = 1;
45   for (int i = 1; i <= x; i++) {
46     s = (s * 2 % p - C(i - 1, y)) % p;
47     ret = (ret + s) % p;
48   }
49   return (ret + p) % p;
50 }
51 
52 int main() {
53 //  freopen("case.in", "r", stdin);
54   int x1, x2, y1, y2;
55   while (scanf("%d%d%d%d%I64d", &x1, &y1, &x2, &y2, &p) != EOF) {
56     init();
57     ll ans1 = (slove(x2, y2) + slove(x1 - 1, y1 - 1)) % p;
58     ll ans2 = ((slove(x1 - 1, y2)) + slove(x2, y1 - 1)) % p;
59     ll ans = (ans1 - ans2) % p;
60     printf("%I64d\n", (ans + p) % p);
61   }
62   return 0;
63 }
代码君

 

题D hdu 5227

题意:给你四元对(t,a,b,k),满足下面条件就是合法的:

1、 1 <= a, b, k <= t

2、 gcd(a,b) >= k

然后给你一颗树,每个点表示一个四元对,随机选两个点,然后这路径上的点就是来玩游戏的点,玩游戏的方法就是每次选一个四元对,然后变成一个更小的合法四元对,然后最后不能操作者输,现在让你算出有多少种选法是必败的?

题解:很容易想到nim,每个四元对当做一堆石头,个数就是比它小的四元对个数,然后假设知道之后我们知道一条路径的异或值为0就是必败的,所以就转化成树分治的求异或值为0的路径数量,这个比较简单,所以本题就难在求比当前四元对小的合法的四元对的数量。

 技术分享

求这个东西太难了,要参考贾志鹏线性筛,以后再学吧,先套个公式吧 !!

 

技术分享
  1 /*zhen hao*/
  2 #include <bits/stdc++.h>
  3 using namespace std;
  4 
  5 #define lson l, m, rt*2
  6 #define rson m + 1, r, rt*2+1
  7 #define xx first
  8 #define yy second
  9 
 10 typedef pair<int,int> pii;
 11 typedef long long ll;
 12 typedef unsigned long long ull;
 13 
 14 const int maxn = 1e4 + 10;
 15 int head[maxn], e = 0, n;
 16 ll phi[maxn], v[maxn], val[maxn];
 17 
 18 struct Edge {
 19   int v, nx;
 20 } edges[maxn * 2];
 21 
 22 ll get(int n, int m) {
 23   if (n > m) swap(n, m);
 24   ll ret = 0;
 25   for (int i = 1, j; i <= n; i = j + 1) {
 26     j = min(n / (n / i), m / (m / i));
 27     ret += 1ll * (phi[j] - phi[i - 1]) * (n / i) * (m / i);
 28   }
 29   return ret;
 30 }
 31 
 32 void phi_table() {
 33   phi[1] = 1;
 34   for (int i = 2; i < maxn; i++) if (!phi[i])
 35     for (int j = i; j < maxn; j += i) {
 36       if (!phi[j]) phi[j] = j;
 37       phi[j] = phi[j] / i * (i - 1);
 38     }
 39   for (int i = 1; i < maxn; i++) phi[i] += phi[i - 1];
 40   for (int i = 1; i < maxn; i++) v[i] = v[i - 1] + get(i, i);
 41 }
 42 
 43 void init() {
 44   e = 0;
 45   memset(head, -1, sizeof head);
 46 }
 47 
 48 void add_edge(int u, int v) {
 49   edges[e] = (Edge){v, head[u]};
 50   head[u] = e++;
 51 }
 52 
 53 int sz[maxn], vis[maxn];
 54 
 55 void dfs_s(int u, int p) {
 56   sz[u] = 1;
 57   for (int i = head[u]; ~i; i = edges[i].nx) {
 58     int v = edges[i].v;
 59     if (v == p || vis[v]) continue;
 60     dfs_s(v, u);
 61     sz[u] += sz[v];
 62   }
 63 }
 64 
 65 int dp[maxn];
 66 
 67 void dfs_t(int& s, int u, int p, int cnt) {
 68   dp[u] = 0;
 69   for (int i = head[u]; ~i; i = edges[i].nx) {
 70     int v = edges[i].v;
 71     if (v == p || vis[v]) continue;
 72     dfs_t(s, v, u, cnt);
 73     dp[u] = max(dp[u], sz[v]);
 74   }
 75   dp[u] = max(dp[u ], cnt - sz[u]);
 76   if (s == -1 || dp[u] < dp[s]) s = u;
 77 }
 78 
 79 ll c1[maxn]; int c;
 80 
 81 void dfs_c(int u, int p, ll d) {
 82   c1[c++] = d;
 83   for (int i = head[u]; ~i; i = edges[i].nx) {
 84     int v = edges[i].v;
 85     if (v == p || vis[v]) continue;
 86     dfs_c(v, u, d ^ val[v]);
 87   }
 88 }
 89 
 90 map<ll,int>::iterator it;
 91 
 92 ll slove(int s) {
 93   dfs_s(s, -1);
 94   int cnt = sz[s], t = s;
 95   s = -1;
 96   dfs_t(s, t, -1, cnt);
 97   vis[s] = 1;
 98   ll ret = 0;
 99   if (!val[s]) ret++;
100   map<ll,int> mp;
101   for (int i = head[s]; ~i; i = edges[i].nx) {
102     int v = edges[i].v;
103     if (vis[v]) continue;
104     c = 0;
105     dfs_c(v, s, val[v]);
106     for (int j = 0; j < c; j++) {
107       if ((c1[j] ^ val[s]) == 0) ret += 2;
108       it = mp.find(c1[j] ^ val[s]);
109       if (it != mp.end()) ret += (*it).yy * 2;
110     }
111     for (int j = 0; j < c; j++) mp[c1[j]]++;
112   }
113   for (int i = head[s]; ~i; i = edges[i].nx) {
114     int v = edges[i].v;
115     if (vis[v]) continue;
116     ret += slove(v);
117   }
118   return ret;
119 }
120 
121 ll gcd(ll a, ll b) {
122   if (!b) return a;
123   return gcd(b, a % b);
124 }
125 
126 int main() {
127 //  freopen("case.in", "r", stdin);
128   phi_table();
129   while (scanf("%d", &n) == 1) {
130     init();
131     for (int i = 1; i < n; i++) {
132       int u, v;
133       scanf("%d%d", &u, &v);
134       add_edge(u, v); add_edge(v, u);
135     }
136     for (int i = 1; i <= n; i++) {
137       int a, b, c, d;
138       scanf("%d%d%d%d", &a, &b, &c, &d);
139       val[i] = v[a - 1] + d - 1;
140       val[i] += get(b - 1, a);
141       val[i] += get(b, c - 1) - get(b - 1, c - 1);
142     }
143     memset(vis, 0, sizeof vis);
144     ll a = 1ll * n * n - slove(1), b = 1ll * n * n;
145     if (!a) puts("0/1");
146     else {
147       ll d = gcd(a, b);
148       printf("%I64d/%I64d\n", a / d, b / d);
149     }
150   }
151   return 0;
152 }
代码君

 

BestCoder Round #40

标签:

原文地址:http://www.cnblogs.com/zhenhao1/p/5510349.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!