首页 > 代码库 > Codeforces Round #259 (Div. 1) (A,B,C)

Codeforces Round #259 (Div. 1) (A,B,C)

Codeforces Round #259 (Div. 1)

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;
}

B:

#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;
}

C:

#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;
}