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