A
题目大意:
- 给定一个n,找出1~n的所有排列中,值最小的一种排列
- 值被定义为, ∑ i = 1 n ( a i % i = = 0 ) \sum_{i=1}^{n}(a_{i}\%i==0) ∑i=1n(ai%i==0)
解法:
- 首先可以发现对于 i = 1 i=1 i=1的情况,不管 a 1 a_{1} a1取什么值都会满足 1 ∣ a 1 1 \mid a_{1} 1∣a1
- 一种构造方法为,第一个位置取最后一个元素,其他位置都取 i − 1 i-1 i−1这个元素,那么值一定为1
#include <iostream>
using namespace std;
int main()
{
int t;
cin >> t;
while(t --)
{
int n;
cin >> n;
cout << n << " ";
for(int i = 1;i < n;i ++) cout << i << " ";
cout << endl;
}
}
B
题目大意:
- 有n个人,现在需要从n个人中邀请一些人参加聚会
- n个人中,有m对朋友,如果一对朋友中的2个人都被邀请了,那么它们平分一块蛋糕,所需蛋糕数量为被邀请人中的朋友对数量
- n个人编号为1~n,如果第 i i i个没有被邀请,那么聚会就会产生 a i a_{i} ai的不快乐值
- 限制蛋糕的数量只能为偶数,问聚会的最小不快乐值是多少
解法:
- 首先假设邀请了所有人,怎么计算目前的需要的蛋糕数量
- 可知,这时候需要的蛋糕数量为m,因为n个人中有m对朋友
- 如果m为偶数,那么所有人都可以邀请
- 如果m为奇数,那么就需要去掉几个人使得朋友对为偶数
- 把朋友关系想象成一张图,那么可以发现这张图边的数量其实就是朋友对的数量,那么去掉一些人使得朋友对数量为偶数,其实也就是在图中去掉几个点使得图中边的数量为偶数
- 那么就可以记录所有点对应的度数
- 那么就考虑去除那些点会让边数为偶数
- 首先如果一个点的度数为奇数,那么这个点去掉可以让边数为偶数
- 然后就是2个相邻点,如果度数都为偶数的话,去掉之后,边数也为偶数,所以答案,就是取这2种情况的最小值
#include <iostream>
using namespace std;
const int N = 1e5 + 10;
int d[N], a[N];
int main()
{
int t;
cin >> t;
while(t --)
{
int n, m;
cin >> n >> m;
for(int i = 1;i <= n;i ++)
{
cin >> a[i];
d[i] = 0;
}
int temp = 0x3f3f3f3f;
for(int i = 1;i <= m;i ++)
{
int u, v;
cin >> u >> v;
d[u] += 1, d[v] += 1;
temp = min(temp, a[u] + a[v]);
}
if(m & 1)
{
int res = 0x3f3f3f3f;
for(int i = 1;i <= n;i ++) if(d[i] & 1) res = min(res, a[i]);
cout << min(res, temp) << endl;
}
else cout << 0 << endl;
}
return 0;
}
C
题目大意:
- 给定一个 n × m n \times m n×m的表格,以及 k k k种颜色,每种颜色最多可以涂 a i a_{i} ai个格子
- 问存不存在一种方案,可以使用这些颜色涂满所有格子,满足对于 ( i , j ) (i, j) (i,j)这个格子,它的相邻格子中至少有3个格子颜色和它一样,这里的相邻比较特殊,指的是如果处于边界,那么相邻的格子出了边界就是对立边界中相应的格子
解法:
- 通过构造几组数据可知,如果一个颜色要被涂上格子,那么这个颜色一定会占用表格的 x x x行或者 x x x列 ( 2 ≤ x ≤ n 或者 m ) (2\le x \le n或者m) (2≤x≤n或者m)
- 那么对于每一种颜色,如果这种颜色可以涂满超过2行或者2列,就记录可以涂的数量,如果最后数量不够 n ∗ m n * m n∗m个,就不行
- 如果数量满足,对于按行的以及按列的再分2种情况,如果按列涂,那么如果有偶数列,就可以实现;如果有奇数列,就还需判断是否存在一个颜色可以涂3列,如果可以就能满足条件,另一种情况类似。
#include <iostream>
using namespace std;
const int N = 1e5 + 10;
int a[N];
typedef long long ll;
int main()
{
int t;
cin >> t;
while(t --)
{
ll n,m,k;
cin >> n >> m >> k;
for(int i = 1;i <= k;i ++) cin >> a[i];
ll res1 = 0, res2 = 0;
for(int i = 1;i <= k;i ++)
{
if(a[i] >= 2 * n)
res1 += (a[i] - a[i] % n);
if(a[i] >= 2 * m)
res2 += (a[i] - a[i] % m);
}
// cout << res1 << " " << res2 << endl;
if((res1 < n * m) && (res2 < n * m)) puts("No");
else
{
int flag = 0;
if(res1 >= n * m)
{
if(m % 2 == 0) flag = 1;
else
{
for(int i = 1;i <= k;i ++)
if(a[i] >= 3 * n) flag = 1;
}
}
if(res2 >= n * m)
{
if(n % 2 == 0) flag = 1;
else
{
for(int i = 1;i <= k;i ++)
if(a[i] >= 3 * m) flag = 1;
}
}
if(flag) puts("Yes");
else puts("No");
}
}
return 0;
}