2017-09-23校训练题题解

t1

题解

定义f[i][j]表示i次操作后x的数值为j的概率。DP转移可以转化为矩阵乘法形式,利用矩阵快速幂进行优化。但是我们发现转移还是矩阵的形式,而且是循环矩阵的形式。循环矩阵快速幂

#include<set>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

inline int read() {
	int x = 0, flag = 1; char ch = getchar();
	while (ch > '9' || ch < '0') { if (ch == '-') flag = -1; ch = getchar(); }
	while (ch <= '9' && ch >= '0') { x = x * 10 + ch - '0'; ch = getchar(); }
	return x * flag;
}

#define rep(ii, aa, bb) for (int ii = aa; ii <=  bb; ii++)
#define drp(ii, aa, bb) for (int ii = aa; ii >= bb; ii--)
#define ha 1000000007
#define ll long long
#define MOD 1001

int n, m, mod, a;
ll ans[MOD][2], t[MOD][2] = {};
int ansPos = 0, tmpPos = 0;

int mult(ll x) {
	ll ret = 1;
	int k = ha - 2;
	while(k) {
		if (k & 1) ret = ret * x % ha;
		x = x * x % ha;
		k >>= 1;
	}
	return ret;
}

void matrixMult() {
	while (m) {
		if (m & 1) {
			ansPos ^= 1;
			rep(i, 1, mod - 1) ans[i][ansPos] = 0;
			rep(i, 1, mod - 1) rep(j, 1, mod - 1)
				ans[i * j % mod][ansPos] += ans[i][ansPos ^ 1] * t[j][tmpPos] % ha;
			rep(i, 1, mod - 1) ans[i][ansPos] %= ha;
		}
		tmpPos ^= 1;
		rep(i, 1, mod - 1) t[i][tmpPos] = 0;
		rep(i, 1, mod - 1) rep(j, 1, mod - 1)
			t[i * j % mod][tmpPos] += t[i][tmpPos ^ 1] * t[j][tmpPos ^ 1] % ha;
		rep(i, 1, mod - 1) t[i][tmpPos] %= ha;
		m >>= 1;
	}
}

int main() {
	n = read(), m = read(), mod = read();
	rep(i, 1, n) t[read()][tmpPos]++;
	int rn = mult(n);
	rep(i, 1, mod - 1) t[i][tmpPos] = t[i][tmpPos] * rn % ha;
	ans[1][ansPos] = 1;
	matrixMult();
	ll ansTot = 0;
	rep(i, 1, mod - 1) ansTot = (ansTot + ans[i][ansPos] * i) % ha;
	printf("%lld\n", ansTot);
	return 0;
}


t2

对于任意一列,两行之间的差相等”是一个很重要的性质.这告诉我们:每一列差分后得到的结果相同.每一行差分后的结果也相同.于是我们对行列分别用带权并查集维护行之间,列之间的差分关系.如果差分关系出现矛盾(两行之间的差值可以推导出两种可能)则无解.如果差分关系没有矛盾,则需要求出整个矩阵中能推导出的最小值判断是否小于0.这里的推导方法是:维护差分关系的并查集必然分成了多个连通块.一种直观的方法是,枚举一个关于行的连通块,再枚举一个关于列的连通块,这两个连通块相交产生的格子中的最小值位于列和行的最小值的交点.这样的时间复杂度是很高的.实际上我们只需考虑每个关于列的连通块.对于一个关于列的连通块,我们求出这个连通块中数值最小的一列.考虑这个连通块中所有的已知数字,每个已知数字都可以求出数值最小的一列中某一个数值.在这些数值中取最小值即可,实现的时候,只需用每个已知数字求出这个连通块中某一列的最小值,再从这一列的最小值转换到最小的一列的最小值.

#include<set>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

inline int read() {
	int x = 0, flag = 1; char ch = getchar();
	while (ch > '9' || ch < '0') { if (ch == '-') flag = -1; ch = getchar(); }
	while (ch <= '9' && ch >= '0') { x = x * 10 + ch - '0'; ch = getchar(); }
	return x * flag;
}

#define rep(ii, aa, bb) for (int ii = aa; ii <=  bb; ii++)
#define ll long long
#define N 200001

struct point {
	int r, c, w;
}pp[N];
int R, C, n;
int fa[N];
int w[N], st[N], mi[N];

bool cmpr(const point &a, const point &b) { return a.c < b.c; }

int find(int x) {
	if (fa[x] == x)	return x;
	int rt = find(fa[x]);
	w[x] += w[fa[x]];
	return fa[x] = rt;
}

bool merge(int a, int b, int c) {
	int ra = find(a), rb = find(b);
	if (ra != rb) {
		fa[ra] = rb;
		w[ra] = c - w[a] + w[b];
		return true;
	}
	else return w[a] == w[b] + c;
}

bool judge() {
	rep(i, 0, n) if (pp[i].w < 0) return 0;
	rep(i, 0, n) fa[i] = i, w[i] = 0;
	sort(pp + 1, pp + 1 + n, cmpr);
	rep(i, 1, n - 1) if(pp[i].c == pp[i + 1].c)
		if(!merge(pp[i].r, pp[i + 1].r, pp[i + 1].w - pp[i].w))	return false;
	memset(st, 0x3f, sizeof(st));
	memset(mi, 0x3f, sizeof(mi));
	rep(i, 1, n) {
		int rt = find(pp[i].r);
		st[rt] = min(st[rt], pp[i].w + w[pp[i].r]);
	}
	rep(i, 0, R) {
		int rt = find(i);
		mi[rt] = min(mi[rt], -w[i]);
	}
	rep(i, 0, R) if (fa[i] == i && st[i] + mi[i] < 0) return false;
	return true;
}

int main() {
	int T = read();
	while (T--) {
		R = read(), C = read(), n = read();
		rep(i, 1, n) pp[i].r = read(), pp[i].c = read(), pp[i].w = read();
		printf("%s\n", judge() ? "Yes" : "No");
	}
	return 0;
}

t3

题面太暴力,题太水(虽然我没写),不挂了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值