123789456ye

已AFO

3.12考试总结

A 小树

题意:51nod 1805
题解:prufer+容斥
由prufer序列性质,度数为1的点不会在里面出现
于是转化为一个长度为\(n-2\)的序列里,总共有\(n\)个元素,恰好有\(m\)个不出现
于是对\(m\)容斥(恰好->至少)
至少\(i\)个不出现的方案数是\(C_{n}^{i}*(n-i)^{n-2}\)
容斥系数是\((-1)^{i-m}*C_{i}^{m}\)
注意特判一下\(n\leq 2\),此时prufer序列不存在,答案为1

#include<bits/stdc++.h>
using namespace std;
#define P 1000000007
#define maxn 1000005
int n, m, inv[maxn], fac[maxn];
inline int qpow(int a, int b)
{
	int ans = 1;
	while (b)
	{
		if (b & 1) ans = 1ll * ans * a % P;
		a = 1ll * a * a % P;
		b >>= 1;
	}
	return ans;
}
inline int c(int x, int y)
{
	return 1ll * fac[x] * inv[y] % P * inv[x - y] % P;
}
int main()
{
	scanf("%d%d", &n, &m);
	if (n <= 2) puts("1");
	else
	{
		fac[0] = inv[0] = 1;
		for (int i = 1; i <= n; ++i) fac[i] = 1ll * fac[i - 1] * i % P;
		inv[n] = qpow(fac[n], P - 2);
		for (int i = n - 1; i; --i) inv[i] = 1ll * inv[i + 1] * (i + 1) % P;
		long long ans = 0;
		for (int i = m, f = 1; i <= n; ++i, f ^= 1)
		{
			if (f) ans += 1ll * c(i, m) * c(n, i) % P * qpow(n - i, n - 2) % P;
			else ans -= 1ll * c(i, m) * c(n, i) % P * qpow(n - i, n - 2) % P;
			ans %= P;
		}
		ans = (ans + P) % P;
		printf("%lld\n", ans);
	}
	return 0;
}

B 搬箱子

题意:51nod 1362
题解:组合数
考虑枚举斜着走了\(i\)

\[\begin{split} F[n][m]&=\sum_{i=0}^{n}C_{n}^{i}C_{n+m-2i}^{n-i} \newline &=\sum_{i=0}^{n}C_{n}^{i}C_{n+m-i}^{m-i} \end{split}\]

因为最后一排任意一点都可以
所以

\[\begin{split} Ans &=\sum_{j=0}^{m}{\sum_{i=0}^{n}C_{n}^{i}C_{n+j-i}^{j-i}}\newline &=\sum_{i=0}^{n}C_{n}^{i}{\sum_{j=0}^{m}{C_{n+j-i}^{j-i}}}\newline &=\sum_{i=0}^{n}C_{n}^{i}C_{n+m-i+1}^{m-i} \end{split}\]

exlucas是什么辣鸡东西!直接分解质因数它不香吗!
这个struct是我本来蒯了以前的exlucas板子,结果T飞了,只好重写

#include<bits/stdc++.h>
using namespace std;
template<typename T>
struct Calculator
{
#define maxn 305
	int P, p[maxn], x, y, cnt, tim[maxn];
	void factor(int x)
	{
		for (int i = 2; i * i <= x; i++)
		{
			if (x % i) continue;
			p[++cnt] = i;
			while (x % i == 0) x /= i;
		}
		if (x > 1) p[++cnt] = x;
	}
	T qpow(T a, int b)
	{
		T ans = 1;
		while (b)
		{
			if (b & 1) ans = ans * a % P;
			a = a * a % P;
			b >>= 1;
		}
		return ans;
	}
	void exgcd(int a, int b, int& x, int& y)
	{
		if (!b)
		{
			x = 1, y = 0;
			return;
		}
		exgcd(b, a % b, y, x);
		y -= a / b * x;
	}
	inline int inv(int a, int b)
	{
		exgcd(a, b, x, y);
		return (x % b + b) % b;
	}
	int get(int x, int tp)
	{
		for (int i = 1; i <= cnt; i++)
		{
			if (x % p[i]) continue;
			int cnt = 0;
			while (x % p[i] == 0) ++cnt, x /= p[i];
			tim[i] += cnt * tp;
		}
		return x;
	}
	int C(int n, int m)
	{
		if (n < m) return 0;
		if (m == 0) return 1;
		memset(tim, 0, sizeof tim);
		T ans = 1;
		for (int i = n - m + 1; i <= n; i++)
			ans = ans * get(i, 1) % P;
		for (int i = 1; i <= m; i++)
			ans = ans * inv(get(i, -1), P) % P;
		for (int i = 1; i <= cnt; i++)ans = ans * qpow(p[i], tim[i]) % P;
		return ans;
	}
};
Calculator<long long> c;
int main()
{
	int n, m, X, ans = 0;
	while (scanf("%d%d%d", &n, &m, &X) != EOF)
	{
		ans = 0; c.P = X; c.factor(X);
		for (int i = 0; i <= n; ++i) ans = (0ll + ans + 1ll * c.C(n, i) * c.C(n + m - i + 1, n + 1)) % X;
		printf("%d\n", ans);
	}
	return 0;
}

C 七星剑

题意:51nod 1705
题解:期望
\(ans[i]\)为第\(i\)颗星的期望
\(i-1 \rightarrow i\)颗星时

\[ans[i]=ans[i-1]+c[i][j]+(1-prob[i][j)*(ans[i]-ans[i-1-lose[i][j]]) \]

化简得

\[ans[i]=\frac{ans[i-1]+c[i][j]-(1-prob[i][j])*ans[i-1-lose[i][j]]}{prob[i][j]} \]

#include<bits/stdc++.h>
using namespace std;
#define maxn 105
#define db long double
#define eps 1e-10
int n, c[maxn], lose[8][maxn];
db prob[8][maxn], ans[maxn];
inline int cmp(db a)
{
	if (a > eps) return 1;
	if (a < -eps) return -1;
	return 0;
}
int main()
{
	scanf("%d", &n);
	for (int i = 1; i <= n; ++i) scanf("%d", &c[i]);
	for (int i = 1; i <= 7; ++i)
	{
		int flag = 0;
		for (int j = 1; j <= n; ++j)
		{
			scanf("%Lf", &prob[i][j]);
			if (cmp(prob[i][j])) flag = 1;
		}
		if (flag == 0)
		{
			puts("-1");
			return 0;
		}
	}
	for (int i = 1; i <= 7; ++i)
		for (int j = 1; j <= n; ++j) scanf("%d", &lose[i][j]);
	for (int i = 1; i <= 7; ++i)
	{
		ans[i] = 1e20;//1e9会爆掉
		for (int j = 1; j <= n; ++j)
			if (cmp(prob[i][j])) 
                            ans[i] = min(ans[i], (ans[i - 1] + c[j] - (1 - prob[i][j]) * ans[i - 1 - lose[i][j]]) / prob[i][j]);
	}
	printf("%.12Lf", ans[7]);
	return 0;
}

D 棋盘游戏

题意:51nod 1327
题解:咕咕咕

posted @ 2020-03-15 15:35  123789456ye  阅读(129)  评论(0编辑  收藏  举报