11/9训练笔记

P5239回忆京都 题解

组合数递推公式递推出前1000*1000项组合数。

预处理一下前缀和。

\(O(1)\)回答。

代码:

#include<iostream>
#define int long long
using namespace std;
int C[1010][1010],s[1010][1010],q,n,m;
signed main()
{
	for(int i = 1;i <= 1000;i++) {
		C[i][i] = 1;
		C[i][0] = 1;
	}
	for(int i = 1;i <= 1000;i++) {
		for(int j = 1;j <= 1000;j++) {
			if(j > i) (C[j][i] = C[j - 1][i] + C[j - 1][i - 1]) %= 19260817;
		}
	}
	/*for(int i = 1;i <= 10;i++) {
		for(int j = 1;j <= 10;j++) {
			cout << C[i][j] << "\t";
		}
		cout << "\n";
	}*/
	for(int i = 1;i <= 1000;i++) {
		for(int j = 1;j <= 1000;j++) {
			s[i][j] = ((s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + C[i][j]) % 19260817 + 19260817) % 19260817;
		}
	}
	cin >> q;
	while(q--) {
		cin >> n >> m;
		swap(n,m);
		cout << s[n][m] << "\n";
	}
}

P6722「MCOI-01」Village 村庄 题解

首先注意到有二分图必有奇环。

同时由于这张图的特殊构造,有奇环必有三元环。

同时,该三元环必包含直径的两个端点。

那么枚举剩下的一个点,判断该三元环是否符合要求即可。

代码:

#include<iostream>
#include<vector>
using namespace std;
int dis1[100010],dis2[100010],t,n,k,x,y,v,mmax,flag,z1,zp1;
vector<pair<int,int> > E[100010];
void Dfs(int x,int fa,int dis) {
	if(dis > mmax) {
		mmax = dis;
		flag = x;
	}
	for(auto i:E[x]) {
		if(i.first == fa) continue;
		Dfs(i.first,x,dis + i.second);
	}
}
void Dfs2(int x,int fa,int dis) {
	dis1[x] = dis;
	for(auto i:E[x]) {
		if(i.first == fa) continue;
		Dfs2(i.first,x,dis + i.second);
	}
}
void Dfs3(int x,int fa,int dis) {
	dis2[x] = dis;
	for(auto i:E[x]) {
		if(i.first == fa) continue;
		Dfs3(i.first,x,dis + i.second);
	}
}
void SolveDiameterOfTree() {
	mmax = 0;
	flag = 0;
	Dfs(1,0,0);
	int z = flag;
	//cout << z << "\n";
	mmax = 0;
	flag = 0;
	Dfs(z,0,0);
	int zp = flag;
	z1 = z;
	zp1 = zp;
}
void CalcDis1(int z1) {
	Dfs2(z1,0,0);
}
void CalcDis2(int zp1) {
	Dfs3(zp1,0,0);
}
int main()
{
	cin >> t;
	loop:while(t--) {
		cin >> n >> k;
		for(int i = 1;i <= n;i++) {
			E[i].clear();
		}
		for(int i = 1;i <= n - 1;i++) {
			cin >> x >> y >> v;
			E[x].push_back({y,v});
			E[y].push_back({x,v});
		}
		SolveDiameterOfTree();
		//cout << z1 << " " << zp1 << "\n";
		CalcDis1(z1);
		CalcDis2(zp1);
		for(int i = 1;i <= n;i++) {
			//cout << dis1[i] << " " << dis2[i] << "\n";
			if(dis1[i] >= k && dis2[i] >= k) {
				cout << "Baka Chino" << "\n";
				goto loop;
			}
		}
		cout << "Yes" << "\n";
	}
}

ABC296F - Simultaneous Swap / 题解

注意到构成\(a,b\)的数组若不同则不行

若逆序对数不同或没有相同元素也不行

否则可以

代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#define int long long
using namespace std;
int a[200010],b[200010],a1[200010],b1[200010],n;
struct BIT{
	int a[500010];
	BIT(){
		memset(a,0,sizeof(a));
	}
	int lowbit(int i) {return i & -i;}
	void Add(int pos) {
		while(pos <= 500000) {
			a[pos]++;
			pos += lowbit(pos);
		}
	}
	int Res(int pos) {
		int res = 0;
		while(pos) {
			res += a[pos];
			pos -= lowbit(pos);
		}
		return res;
	}
};
signed main()
{
	cin >> n;
	for(int i = 1;i <= n;i++) {
		cin >> a[i];
		a1[i] = a[i];
	}
	for(int i = 1;i <= n;i++) {
		cin >> b[i];
		b1[i] = b[i];
	}
	sort(a1 + 1,a1 + n + 1);
	sort(b1 + 1,b1 + n + 1);
	for(int i = n;i >= 1;i--) {
		if(a1[i] != b1[i]) {
			cout << "No" << "\n";
			return 0;
		}
	}
	int flag = 0;
	BIT tr1;
	int ans1 = 0;
	for(int i = n;i >= 1;i--) {
		if(a1[i] == a1[i + 1] && i < n) flag = 1;
		ans1 += tr1.Res(a[i] - 1);
		tr1.Add(a[i]);
	}
	BIT tr2;
	int ans2 = 0;
	for(int i = n;i >= 1;i--) {
		if(b1[i] == b1[i + 1] && i < n) flag = 1;
		ans2 += tr2.Res(b[i] - 1);
		tr2.Add(b[i]);
	}
	if(flag) {
		cout << "Yes" << "\n";
		return 0;
	}
	if(ans1 % 2 != ans2 % 2 && !flag) {
		cout << "No" << "\n";
	} else {
		cout << "Yes" << "\n";
	}
}
posted @ 2023-11-09 19:42  IANYEYZ  阅读(10)  评论(0编辑  收藏  举报