A题:最大值为i的期望为(in−(i−1)n)∗i/mn,那么总期望为∑m1(in−(i−1)n)∗i/mn,然后化简一下公式,答案为m−∑m−11i/mn
B题:状压DP,只需要用到小于59的素数,一共有16个,dp[n][s]表示当前放到第n个数字,素数使用的集合为s的最小值,S[k]表示k数字对应会用掉哪几个素数,然后进行状态转移
dp(n, s) = dp(n - 1, s^S[k]) + abs(k - num[n])
C题:dfs构造,题目中其实给了提示,最多不超过4n步,那么其实如果给定的是一棵树,在这个步骤内是绝对有办法构造出来的,可以选一个根结点出来,然后当成一棵树,对于一条路径,如果走两遍,其实就等于没走,那么对于每条路径,只需要走一遍走到底,再走回根结点,如果当前一个位置不满足,就退一步在进一步,然后注意根结点,其实根结点是无法回退的,但是其实根结点如果不满足,那么我只要让最后回到根结点的一步不走就可以了,这样搜完,在判断一下还有没结点不满足,如果有,肯定是多棵树构造不出来的情况
代码:
A:
#include <cstdio> #include <cstring> #include <cmath> int m, n; int main() { scanf("%d%d", &m, &n); double ans = 0; for (int i = 1; i < m; i++) ans += pow((m - i) * 1.0 / m, n); printf("%.12lf\n", m * 1.0 - ans); return 0; }
#include <cstdio> #include <cstring> #include <cstdlib> const int N = 105; const int MAXN = (1<<16) + 5; const int INF = 0x3f3f3f3f; int n, num[N], prime[N], pn = 0, vis[N], to[N]; void get_prime() { for (int i = 2; i < 59; i++) { if (vis[i]) continue; prime[pn++] = i; for (int j = i * i; j < 60; j += i) { vis[j] = 1; } } } int tra(int num) { int ans = 0; for (int i = 0; i < pn; i++) { if (num % prime[i] == 0) ans |= (1<<i); while (num % prime[i] == 0) num /= prime[i]; } return ans; } int dp[N][MAXN], zh[N][MAXN][2]; void print(int now, int s) { if (now == 0) return; print(now - 1, zh[now][s][0]); printf("%d%c", zh[now][s][1], now == n? '\n' : ' '); } int main() { get_prime(); scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", &num[i]); for (int i = 1; i < 59; i++) to[i] = tra(i); int maxs = (1<<pn); memset(dp, INF, sizeof(dp)); memset(dp[0], 0, sizeof(dp[0])); for (int i = 1; i <= n; i++) { for (int j = 0; j < maxs; j++) { for (int k = 1; k < 60; k++) { if ((j&to[k]) != to[k]) continue; int tmp = dp[i - 1][j^to[k]] + abs(k - num[i]); if (dp[i][j] > tmp) { dp[i][j] = tmp; zh[i][j][0] = (j^to[k]); zh[i][j][1] = k; } } } } int Min = INF, Min_v; for (int i = 0; i < maxs; i++) { if (dp[n][i] < Min) { dp[n][i] = Min; Min_v = i; } } print(n, Min_v); return 0; }
#include <cstdio> #include <cstring> #include <vector> using namespace std; const int N = 100005; int n, m, x[N], now[N], vis[N], nv; vector<int> g[N], ans; void dfs(int u, int p) { vis[u] = 1; ans.push_back(u); now[u] ^= 1; for (int i = 0; i < g[u].size(); i++) { int v = g[u][i]; if (vis[v]) continue; dfs(v, u); } if (x[u]^now[u]) { if (p != 0) { ans.push_back(p); ans.push_back(u); now[p] ^= 1; now[u] ^= 1; } } if (p != 0) { ans.push_back(p); now[p] ^= 1; } } bool judge() { if (x[nv]^now[nv]) { if (ans.size() == 0) return false; now[nv] ^= 1; ans.pop_back(); } for (int i = 1; i <= n; i++) if (x[i]^now[i]) return false; return true; } int main() { scanf("%d%d", &n, &m); int u, v; while (m--) { scanf("%d%d", &u, &v); g[u].push_back(v); g[v].push_back(u); } for (int i = 1; i <= n; i++) scanf("%d", &x[i]); memset(now, 0, sizeof(now)); for (int i = 1; i <= n; i++) { if (x[i]^now[i]) { nv = i; dfs(i, 0); break; } } if (judge()) { int tmp = ans.size(); printf("%d\n", tmp); for (int i = 0; i < tmp; i++) { printf("%d%c", ans[i], i == ans.size() - 1 ? '\n' : ' '); } } else printf("-1\n"); return 0; }