HDU 4655 Cut Pieces
假设n个数构成的总数都分成了n段,总数是n*a1*a2*...*an。但是答案显然不会那么多。
对于相邻的两个ai,ai+1,如果选择相同的颜色,那么就减少了a1*a2*...*ai-1*min(ai,ai+1)*ai+2*ai+3*...*an。
不妨假设n=3,三个数分别是a,b,c。且a<b<c。
对于所有的排列,只有a,c,b是最优的,结果是3*a*b*c-a*b-b。
当n>3的时候同样可以得到结论:a1,an,a2,an-1...使得总的段数最多。
1 #include<cstdio> 2 #include<algorithm> 3 #include<iostream> 4 typedef long long LL; 5 #define MOD 1000000007 6 #define MAXN 1000010 7 using namespace std; 8 int arr[MAXN]; 9 int tmp[MAXN]; 10 LL ext_gcd(LL a, LL b, LL &x, LL &y) { 11 LL t, d; 12 if (b == 0) { 13 x = 1; 14 y = 0; 15 return a; 16 } 17 d = ext_gcd(b, a % b, x, y); 18 t = x; 19 x = y; 20 y = t - a / b * y; 21 return d; 22 } 23 LL invmod(LL a, LL n = MOD) { 24 LL x, y; 25 if (ext_gcd(a, n, x, y) != 1) 26 return -1; 27 return (x % n + n) % n; 28 } 29 int main() { 30 int T; 31 int n; 32 int i; 33 LL ans; 34 LL res; 35 LL mul; 36 int l, r; 37 scanf("%d", &T); 38 while (T--) { 39 scanf("%d", &n); 40 ans = n; 41 mul = 1; 42 for (i = 0; i < n; i++) { 43 scanf("%d", &arr[i]); 44 mul *= arr[i]; 45 mul %= MOD; 46 } 47 ans *= mul; 48 ans %= MOD; 49 sort(arr, arr + n); 50 for (l = 0, r = n - 1, i = 1; l <= r; l++, r--) { 51 if (l == r) { 52 tmp[i++] = arr[l]; 53 } else { 54 tmp[i++] = arr[l]; 55 tmp[i++] = arr[r]; 56 } 57 } 58 for (i = 2; i <= n; i++) { 59 res = mul * invmod(tmp[i] * (LL) tmp[i - 1]); 60 res %= MOD; 61 res *= min(tmp[i], tmp[i - 1]); 62 ans -= res % MOD; 63 ans = (ans % MOD + MOD) % MOD; 64 } 65 cout << ans << endl; 66 } 67 return 0; 68 }
HDU 4661 Message Passing
由于消息传递的次数要求最少,则一个节点将收集所有它的子树的消息之后,再往父节点传递。
因此,有一个节点将收到所有消息。而发送消息是收集消息的逆过程,总的答案=收集消息的方案数*发送消息的方案数=收集消息的方案数2。
dp[i]表示以i为根的子树,收集到它子孙所有消息的方案数。
size[i]表示以i为根的子树的节点总数。
f[i]表示以i为根的树,收集到它子孙所有消息的方案数。
fac[i]表示i的阶乘。
dp[i]=fac[size[i]-1]。
dp[i]/=fac[size[j]],(j是i的儿子)。
dp[i]*=dp[j],(j是i的儿子)。
1 #pragma comment(linker,"/STACK:102400000,102400000") 2 #include<cstdio> 3 #include<cstring> 4 typedef long long LL; 5 #define MAXN 1000010 6 #define MAXM 2000010 7 #define MOD 1000000007 8 int n; 9 LL fac[MAXN]; 10 LL invfac[MAXN]; 11 int first[MAXN], next[MAXM], v[MAXM], e; 12 bool vis[MAXN]; 13 LL dp[MAXN]; 14 LL f[MAXN]; 15 int size[MAXN]; 16 LL ext_gcd(LL a, LL b, LL &x, LL &y) { 17 LL t, d; 18 if (b == 0) { 19 x = 1; 20 y = 0; 21 return a; 22 } 23 d = ext_gcd(b, a % b, x, y); 24 t = x; 25 x = y; 26 y = t - a / b * y; 27 return d; 28 } 29 LL invmod(LL a, LL n = MOD) { 30 LL x, y; 31 if (ext_gcd(a, n, x, y) != 1) 32 return -1; 33 return (x % n + n) % n; 34 } 35 void init() { 36 int i; 37 fac[0] = 1; 38 for (i = 1; i < MAXN; i++) { 39 fac[i] = fac[i - 1] * i; 40 fac[i] %= MOD; 41 } 42 for (i = 0; i < MAXN; i++) { 43 invfac[i] = invmod(fac[i]); 44 } 45 } 46 inline void addEdge(int x, int y) { 47 v[e] = y; 48 next[e] = first[x]; 49 first[x] = e++; 50 } 51 void getSize(int x) { 52 vis[x] = true; 53 size[x] = 1; 54 for (int i = first[x]; i != -1; i = next[i]) { 55 int y = v[i]; 56 if (!vis[y]) { 57 getSize(y); 58 size[x] += size[y]; 59 } 60 } 61 } 62 void dfs(int x) { 63 vis[x] = true; 64 dp[x] = fac[size[x] - 1]; 65 for (int i = first[x]; i != -1; i = next[i]) { 66 int y = v[i]; 67 if (!vis[y]) { 68 dfs(y); 69 dp[x] *= invfac[size[y]]; 70 dp[x] %= MOD; 71 dp[x] *= dp[y]; 72 dp[x] %= MOD; 73 } 74 } 75 } 76 void search(int x, int pre) { 77 vis[x] = true; 78 if (pre != -1) { 79 f[x] = fac[n - 1]; 80 81 f[x] *= invfac[n - size[x]]; 82 f[x] %= MOD; 83 LL tmp = f[pre]; 84 tmp *= invfac[n - 1]; 85 tmp %= MOD; 86 tmp *= fac[n - 1 - size[x]]; 87 tmp %= MOD; 88 tmp *= fac[size[x]]; 89 tmp %= MOD; 90 tmp *= invmod(dp[x]); 91 tmp %= MOD; 92 f[x] *= tmp; 93 f[x] %= MOD; 94 for (int i = first[x]; i != -1; i = next[i]) { 95 int y = v[i]; 96 if (!vis[y]) { 97 f[x] *= invfac[size[y]]; 98 f[x] %= MOD; 99 f[x] *= dp[y]; 100 f[x] %= MOD; 101 } 102 } 103 } 104 for (int i = first[x]; i != -1; i = next[i]) { 105 int y = v[i]; 106 if (!vis[y]) { 107 search(y, x); 108 } 109 } 110 } 111 int main() { 112 int T; 113 int i; 114 int x, y; 115 int ans; 116 init(); 117 scanf("%d", &T); 118 while (T--) { 119 scanf("%d", &n); 120 e = 0; 121 memset(first, -1, sizeof(first)); 122 for (i = 1; i < n; i++) { 123 scanf("%d%d", &x, &y); 124 addEdge(x, y); 125 addEdge(y, x); 126 } 127 memset(vis, false, sizeof(vis)); 128 getSize(1); 129 memset(vis, false, sizeof(vis)); 130 dfs(1); 131 memset(vis, false, sizeof(vis)); 132 f[1] = dp[1]; 133 search(1, -1); 134 ans = 0; 135 for (i = 1; i <= n; i++) { 136 ans += (f[i] * f[i]) % MOD; 137 ans %= MOD; 138 } 139 printf("%d\n", ans); 140 } 141 return 0; 142 }
HDU 4662 MU Puzzle
从给定的字符串变成MI需要反着操作。
(1)将U替换成III。
(2)添加x个UU,即添加x个IIIIII。
假设有cnt个I,添加x个UU,那么一共有cnt+6x个I,又要满足cnt+6x=2y。判断是否存在这样的x满足方程即可。
1 #include<cstdio> 2 #include<cstring> 3 #define MAXN 1000010 4 char str[MAXN]; 5 bool isOK(int len) { 6 if (str[0] != 'M') { 7 return false; 8 } 9 for (int i = 1; i < len; i++) { 10 if (str[i] == 'M') { 11 return false; 12 } 13 } 14 return true; 15 } 16 int main() { 17 int T; 18 int len; 19 int cnt; 20 int i; 21 scanf("%d", &T); 22 while (T--) { 23 scanf(" %s", str); 24 len = strlen(str); 25 if (isOK(len)) { 26 cnt = 0; 27 for (i = 1; i < len; i++) { 28 if (str[i] == 'U') { 29 cnt += 3; 30 } else { 31 cnt++; 32 } 33 } 34 if (len == 2 && str[1] == 'I') { 35 puts("Yes"); 36 } else if (cnt % 6 == 2 || cnt % 6 == 4) { 37 puts("Yes"); 38 } else { 39 puts("No"); 40 } 41 } else { 42 puts("No"); 43 } 44 } 45 return 0; 46 }
HDU 4664 Triangulation
SG打表找规律。
mex是不属于这个集合的最少非负整数。
sg(x)是mex{sg(y)|y是x的后继状态}。
游戏和的SG函数值是它的所有子游戏SG函数值的异或。
n个游戏的异或和为0,先手必败。
1 #include<cstdio> 2 #include<cstring> 3 #define MAXN 1010 4 int sg[MAXN]; 5 bool vis[MAXN]; 6 int SG(int n) { 7 if (n == 0) { 8 sg[n] = 0; 9 } else if (n == 1) { 10 sg[n] = 0; 11 } else if (n == 2) { 12 sg[n] = 1; 13 } else if (n == 3) { 14 sg[n] = 1; 15 } else if (sg[n] == -1) { 16 int i; 17 memset(vis, false, sizeof(vis)); 18 for (i = 0; i <= n - 2; i++) { 19 vis[SG(i) ^ SG(n - i - 2)] = true; 20 } 21 for (i = 0;; i++) { 22 if (!vis[i]) { 23 break; 24 } 25 } 26 sg[n] = i; 27 } 28 return sg[n]; 29 } 30 void init() { 31 int i; 32 memset(sg, -1, sizeof(sg)); 33 for (i = 0; i < MAXN; i++) { 34 sg[i] = SG(i); 35 } 36 } 37 int getSG(int n) { 38 if (n < MAXN) { 39 return sg[n]; 40 } else { 41 return sg[n % 34 + 2 * 34]; 42 } 43 } 44 int main() { 45 int T; 46 int n; 47 int tmp; 48 int res; 49 init(); 50 scanf("%d", &T); 51 while (T--) { 52 scanf("%d", &n); 53 res = 0; 54 while (n--) { 55 scanf("%d", &tmp); 56 res ^= getSG(tmp); 57 } 58 if (res) { 59 puts("Carol"); 60 } else { 61 puts("Dave"); 62 } 63 } 64 return 0; 65 }
HDU 4665 Unshuffle
若一个数只出现两次,则第一个数属于0,第二个数属于1。
若一个数出现了四次,则第一个数属于0,第四个数属于1,其他两个都有可能。
1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 #define MAXN 2010 5 using namespace std; 6 int arr[MAXN]; 7 char str[MAXN]; 8 bool flag; 9 int idx[MAXN]; 10 int cnt[MAXN]; 11 int st[2][MAXN]; 12 int belong[MAXN]; 13 int n; 14 vector<int> pos[MAXN]; 15 void dfs(int x, int p1, int p2) { 16 if (x > n) { 17 flag = true; 18 } 19 if (flag) { 20 return; 21 } 22 if (p1 > 0 && p2 > 0 23 && arr[st[0][min(p1, p2)]] != arr[st[1][min(p1, p2)]]) { 24 return; 25 } 26 if (belong[x] == 0) { 27 st[0][p1 + 1] = x; 28 dfs(x + 1, p1 + 1, p2); 29 } else if (belong[x] == 1) { 30 st[1][p2 + 1] = x; 31 dfs(x + 1, p1, p2 + 1); 32 } else { 33 st[0][p1 + 1] = x; 34 belong[pos[arr[x]][2]] = 1; 35 dfs(x + 1, p1 + 1, p2); 36 37 if (!flag) { 38 st[1][p2 + 1] = x; 39 belong[pos[arr[x]][2]] = 0; 40 dfs(x + 1, p1, p2 + 1); 41 42 belong[pos[arr[x]][2]] = -1; 43 } 44 } 45 } 46 int main() { 47 int T; 48 int i; 49 scanf("%d", &T); 50 while (T--) { 51 scanf("%d", &n); 52 memset(idx, 0, sizeof(idx)); 53 memset(cnt, 0, sizeof(cnt)); 54 for (i = 1; i <= n; i++) { 55 scanf("%d", &arr[i]); 56 cnt[arr[i]]++; 57 idx[i] = cnt[arr[i]]; 58 pos[arr[i]].clear(); 59 } 60 memset(belong, -1, sizeof(belong)); 61 for (i = 1; i <= n; i++) { 62 if (idx[i] == 1) { 63 belong[i] = 0; 64 } else if (idx[i] == 2 && cnt[arr[i]] == 2) { 65 belong[i] = 1; 66 } else if (idx[i] == 4) { 67 belong[i] = 1; 68 } 69 pos[arr[i]].push_back(i); 70 } 71 flag = false; 72 dfs(1, 0, 0); 73 for (i = 1; i <= (n >> 1); i++) { 74 str[st[0][i]] = '0'; 75 str[st[1][i]] = '1'; 76 } 77 for (i = 1; i <= n; i++) { 78 putchar(str[i]); 79 } 80 putchar('\n'); 81 } 82 return 0; 83 }