Codeforces Round #663 (Div. 2)

A. Suborrays

题意:

输入一个长度 n n n,用 1 n 1 n 1n 的数字进行随机排列。定义对于一个正整数 n n n,如果对于每一对 i i i j ( 1 ≤ i ≤ j ≤ n ) j(1≤i≤j≤n) j(1ijn) 都满足,对于 p p p 的每个子数组,其中所有元素的 O R OR OR 不小于该子数列中元素的个数。我们称长度为 n n n 的排列 p p p 是好的。

两个数进行位运算了,且范围是 1   n 1~n 1 n,那么进行位运算后的结果不会小于元素的个数。简而言之就是:无论怎么输出这个置换序列都是正确的。

AC代码:
int t;
int n,m;
int ans[N];
int main()
{
	sd(t);
	while (t--)
	{
		sd(n);
 
		rep(i,1,n)
		printf("%d%c",i,i==n?'\n':' ');
	}
}

B. Fix You

题意:

给定一个 n ∗ m n∗m nm 的网格传送带,每个传送带上都有一个方向为, D D D 代表向下, R R R 代表向右。我们可以改变传送的的方向。(只能在下右之间做调整。)其中 ( n , m ) (n,m) (n,m) 处为柜台,我们要使得网格传送带上的行李都能到达柜台处,求我们至少要进行多少次操作更改。

因为只有向下和向右,所以把全部的边缘给改变了就行。

AC代码:
const int N = 2010;
 
int t;
int n, m;
char a[200][200];
int main()
{
	sd(t);
	while (t--)
	{
		sdd(n, m);
		rep(i, 1, n)
		{
			rep(j, 1, m)
			{
				cin >> a[i][j];
			}
		}
		int ans = 0;
		rep(i, 1, n - 1)
		{
			if (a[i][m] == 'R')
				ans++;
		}
		rep(j, 1, m - 1)
		{
			if (a[n][j] == 'D')
				ans++;
		}
		pd(ans);
	}
	return 0;
}

C. Cyclic Permutations

题意:

对于所有长度为 n n n 的排列,找出有多少个满足其中存在至少一个简单环。(对于排列中的每个值 a [ i ] a[i] a[i],和其左右两边第一个大于它的 a [ j ] a[j] a[j] 连一条无向边)

满足条件的排列数等于总排列数-不满足条件的排列数。
而不满足条件的排列数通过找规律:
n = 4 n = 4 n=4时:
不满足条件的排列有:

1234 1234 1234
4321 4321 4321
1342 1342 1342
2431 2431 2431
1243 1243 1243
3421 3421 3421
1432 1432 1432
2341 2341 2341
一共八个,但可以分为 4 4 4 组。一位第 1 , 2 1,2 1,2,第 3 , 4 3,4 3,4,第 5 , 6 5,6 56,第 7 , 8 7,8 7,8个排列,分别是 r e v e r s e reverse reverse 的。那么只分析第 1 , 3 , 5 , 7 1,3,5,7 1,3,5,7 个排列。我们发现。其实规律只与排列中的最小数字 1 1 1 和最大数字 n n n 的位置有关。
如将排列写成 1 … n … 1…n… 1n形式。则 1 1 1 n n n 之间的数字必须升序, n n n后的数字必须降序。那么我们只需考虑 1 1 1 n n n 之间数字的个数即可。

1 1 1 n n n 之间数字的个数取值范围是 [ 0 , n − 2 ] [0,n-2] [0,n2],假如 1 1 1 n n n 之间放 i i i 个数 ( i < = n − 2 ) (i <= n-2) i<=n2,又因为这 i i i 个数一定是升序,所以是组合数 C n − 2 i C_{n-2}^i Cn2i

那么可见,不满足条件的排列数为 2 ∗ ( C n − 2 2 + C n − 2 1 + C n − 2 2 + … + C n − 2 n − 2 ) = 2 ∗ 2 n − 2 = 2 n − 1 2*(C_{n-2}^2+C_{n-2}^1+C_{n-2}^2+…+C_{n-2}^{n-2})= 2* 2^ n-2 = 2^ {n-1} 2Cn22+Cn21+Cn22++Cn2n2=22n2=2n1
而全排列个数为 n ! n! n!,所以答案就是 n ! − 2 n − 1 n! - 2^ {n-1} n!2n1

AC代码:
ll qpow(ll x, ll n, ll mod)
{
	ll res = 1;
	while (n)
	{
		if (n & 1)
			res = (res * x) % mod;
		x = x * x % mod, n >>= 1;
	}
	return res;
}
 
const int N = 2010;
const int mod = 1e9 + 7;
int t;
ll n, m;
char a[200][200];
int main()
{
	sld(n);
	ll ans = 1;
	rep(i, 1, n)
		ans = (ans * i) % mod;
	ans = (ans - qpow(2, n - 1, mod)) % mod;
	pld((ans % mod + mod) % mod);
	return 0;
}

D. 505

题意:

给定一个 n × m n×m n×m 01 01 01 矩阵,求至少要改多少个元素,使得每个边长为偶数的正方形都包含奇数个 1 1 1。或无解。

若存在边长为 4 4 4 的正方形,肯定是无解的。因为将它拆成 4 4 4 个边长为 2 2 2 的正方形,奇+奇+奇+奇=偶。

  • n = 1 n=1 n=1 :显然答案为 0 0 0

  • n = 2 n=2 n=2:每列的 1 1 1的数量的奇偶性显然只有 [ 1 , 0 , 1 , 0 , ⋯ ] [1,0,1,0,⋯] [1,0,1,0,] [ 0 , 1 , 0 , 1 , ⋯ ] [0,1,0,1,⋯] [0,1,0,1,] 两种,都算一下比个大小即可;

  • n = 3 n=3 n=3:每列上下两个 2 × 1 2×1 2×1 矩阵的1的数量的奇偶性显然只有
    四种,易证每列最多修改 1 1 1次,都算一下比个大小即可。

AC代码:
const int N = 1000000;
int n, m;
vector<string> v;
bool a[4][N + 1];
 
int main()
{
	sdd(n, m);
	if (n >= 4 && m >= 4)
	{
		puts("-1");
		return 0;
	}
	rep(i, 1, n)
	{
		string a;
		cin >> a;
		v.pb(a);
	}
	if (n >= 4)
	{
		rep(i, 1, n)
		{
			rep(j, 1, m)
				a[j][i] = v[i - 1][j - 1] ^ 48;
		}
		swap(n, m);
	}
	else
	{
		rep(i, 1, n)
		{
			rep(j, 1, m)
				a[i][j] = v[i - 1][j - 1] ^ 48;
		}
	}
	if (n == 1)
		puts("0");
	else if (n == 2)
	{
		int ans = 0;
		rep(i, 1, m)
		{
			ans += (a[1][i] ^ a[2][i]) == (i & 1);
		}
		pd(min(ans, m - ans));
	}
	else
	{
		int ans1 = 0, ans2 = 0, ans3 = 0, ans4 = 0;
		rep(i, 1, m)
			ans1 += (a[1][i] ^ a[2][i]) != (i & 1) || (a[2][i] ^ a[3][i]) != (i & 1);
		rep(i, 1, m)
			ans2 += (a[1][i] ^ a[2][i]) == (i & 1) || (a[2][i] ^ a[3][i]) != (i & 1);
		rep(i, 1, m)
			ans3 += (a[1][i] ^ a[2][i]) != (i & 1) || (a[2][i] ^ a[3][i]) == (i & 1);
		rep(i, 1, m)
			ans4 += (a[1][i] ^ a[2][i]) == (i & 1) || (a[2][i] ^ a[3][i]) == (i & 1);
		pd(min(min(ans1, ans2), min(ans3, ans4)));
	}
	return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值