Codeforces Round #745 Div.2 A~C
A. CQXYM Count Permutations
求长度为\(2n\)的排列\(p\),且\(p\)中满足\([p_i < p_{i+1}]\)的总对数不少于\(n\)的排列\(p\)的个数。
猜想:\(\frac 1 2(2n)!\)。
证明:假定一个排列\(p\)中\([p_i<p_{i+1}]\)的对数为\(k\),那么对于排列\(q_i = 2n - p_i\),排列\(q\)中\([q_i<q_{i+1}]\)的对数一定是\(2n - k - 1\)(被减后大小顺序一定会发生改变)。因此类推下来\(k≥n\)的排列\(p\)的个数是总排列数的一半。
void solve() {
int n;scanf("%d",&n);
LL res = 1;
for (int i = 3;i <= 2 * n;++i) {
res = res * i % MOD;
}
printf("%lld\n",res);
}
B. Diameter of Graph
求顶点个数为\(n\),边数为\(m\),直径最大为\(k-2\)的无向连通图是否合法(不允许有自环、重边)。
首先考虑孤立点,\(n = 1\)时必须满足\(m = 0\),\(k≥2\),否则不合法。
接着考虑一般情况,\(m<n-1\)图不连通,\(m > n * (n-1) / 2\)的时候有重边,\(k = 3\)的时候只能是\(m = n * (n-1)/2\),其他任何情况都能构造菊花图使得直径为2,最后只要不是孤立点,\(k>2\)。
void solve() {
LL n,m,k;
cin >> n >> m >> k;
k = k - 2;
if (n == 1) {
if (m != 0 || k < 0){
cout << "NO\n";
}else {
cout << "YES\n";
}
return;
}
if (m > n * (n - 1) / 2 || k <= 0 || m < n - 1) {
cout << "NO\n";
}else if (k == 1 && m != (n - 1) * n / 2){
cout << "NO\n";
}else cout << "YES\n";
}
C. Portal
题意让你用黑曜石构造一个地狱传送门。
可以枚举门的左上角和右下角,从而算出门需要的改变量。由于用1,0表示,我们可以直接用二维前缀和求出线段的和与实际的差。
时间:\(O(n^4)\)
注意最后一重循环表示该门向右拓展的趋势。那么如果上左下中的该变量已经比最小值要大了,那么此解一定不是答案,以此剪枝。
int a[405][405];
int pre[405][405];
int query(int j,int k,int l,int m) {
return pre[l][m] - pre[j - 1][m] - pre[l][k-1] + pre[j-1][k-1];
}
void solve() {
int n,m;
scanf("%d%d",&n,&m);
getchar();
for (int i = 1;i <= n;++i) {
for (int j = 1;j <= m;++j) {
a[i][j] = getchar() - '0';
}
getchar();
}
for (int i = 1;i <= n;++i) {
for (int j = 1;j <=m;++j) {
pre[i][j] = pre[i - 1][j] + pre[i][j - 1] - pre[i - 1][j - 1] + a[i][j];
}
}
int res = INF;
for (int i = 1;i <= n;++i) {
for (int j = 1;j <= m;++j) {
for (int k = i + 4;k <= n;++k) {
for (int l = j + 3;l <= m;++l) {
int top = l-j-1 - query(i,j+1,i,l-1);
int but = l-j-1 - query(k,j+1,k,l-1);
int left = k-i-1 - query(i+1,j,k-1,j);
int right = k-i-1 - query(i+1,l,k-1,l);
int center = query(i+1,j+1,k-1,l-1);
if (top + but + left + center >= res) break;
/*
if (top + but + left + right + center < res) {
cout << i << ' ' << j << endl;
cout << k << ' ' << l << endl;
cout << "top: " << top << endl;
cout << "but: " << but << endl;
cout << "left: " << left << endl;
cout << "right: " << right << endl;
cout << "center: " << center << endl;
}
*/
res = min(res,top+but+left+right+center);
}
}
}
}
printf("%d\n",res);
}

浙公网安备 33010602011771号