A. Sum of Odd Integers
题目大意:
给你一个数n,要求分为k个奇数(每个都不相同),可以的话就yes,否则就是no。
题解:
我们从k=num来说,最小的奇数和为odd_sum=num*num。条件1:然而n必须大于等于odd_sum。两个奇数之和为偶数。当k为奇数,k个奇数和为奇数,所以n为奇数。当k为偶数时,k个奇数的和为偶数,所以n为偶数。条件2:n与k的奇偶性相同。
ACcode:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const double PI = acos(-1.0);
int main()
{
ios::sync_with_stdio(false);
int t;
cin >> t;
while (t--)
{
bool flag = 0;
ll a, b;
cin >> a >> b;
if (a >= b * b)
if (b % 2 == a % 2)
flag = 1;
if (flag)
cout << "YES" << endl;
else
cout << "NO" << endl;
}
return 0;
}
B. Princesses and Princes
题目大意:
有n个公主和n个王子,每个公主有一份自己满意的王子名单,n较小的公主会优先选择他的名单中没有被选走的n最小的王子,如果王子全被选走,则没有结婚。现在国王有机会让一个公主的名单多一个人,尽可能让更多公主结婚,请问能否做到,如果能,给那位公主加那位王子,如果不能直接输出Optimal。
题解:
模拟题。我们先设立一个bool数组,用来判断王子是否被选择过。再设立一个vector数组,用来存入暂时没有结婚的公主编号。然后先全部遍历完后,把vector数组遍历,并1到n遍历王子,若有没有被标记则直接输出;若都没有,则就不能。
ACcode:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const double PI = acos(-1.0);
const int maxn = 1e5 + 5;
int main()
{
ios::sync_with_stdio(false);
int t;
cin >> t;
while (t--)
{
int n, m;
bool v[maxn] = {0};
int cnt = 0;
vector<int> a;
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> m;
int num;
bool flag = 0;
for (int j = 1; j <= m; j++)
{
cin >> num;
if (v[num] == 0 && flag == 0)
{
v[num] = 1;
flag = 1;
}
}
if (flag == 0)
a.push_back(i);
}
bool flag1 = 0;
for (int i = 0; i < a.size(); i++)
{
for (int j = 1; j <= n; j++)
{
if (v[j] == 0)
{
cout << "IMPROVE" << endl;
cout << a[i] << " " << j << endl;
flag1 = 1;
break;
}
}
if (flag1)
break;
}
if (flag1 == 0)
cout << "OPTIMAL" << endl;
}
return 0;
}
C. Game with Chips
题目大意:
在n*m的矩阵中,给你k个起始坐标,k个对应的k个终点坐标。现在让你在2nm步内,让k个坐标至少经过一次对应的终点坐标。
题解:
重点在于2nm步,这就说明能遍历两遍,我们首先将所有点集中在(1,1)点,然后开始遍历所有点。
ACcode:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const double PI = acos(-1.0);
const int N = 1e5 + 5;
int main()
{
ios::sync_with_stdio(false);
int n, m, k, x, y;
cin >> n >> m >> k;
string ans;
for (int i = 1; i <= k; i++)
cin >> x >> y;
for (int i = 1; i <= k; i++)
cin >> x >> y;
for (int i = 1; i < n; i++) //u,d
ans += 'U';
for (int i = 1; i < m; i++) //l,r
ans += 'L';
for (int i = 1; i <= n; i++)
{
for (int j = 1; j < m; j++)
{
if (i % 2 == 1)
ans += 'R';
else
ans += 'L';
}
if (i != n)
ans += 'D';
}
cout << ans.size() << endl;
cout << ans << endl;
return 0;
}
E. Count The Blocks
题目大意:
给你一个n,代表从0到10^n-1的所有数(有前导0)。我们现在定义块的长度len,代表在所有数中,有长度为len的数全部相同,这个块的前后的数与其都不同。例如:00027734000,len=1有3个(2,3,4),len=2有1个(77),len=3有2个(000,000);问len从1到n,满足定义的个数为多少,并输出。
题解:
组合数问题。
我们先分为两种方式:
- 只记录当前数字的最前端和最后端两块的。如001112225,前端为00,后端为5。
- 除方式1以外的所有。也就是说,相对于中间的。
计算方式:
-
我们将长度为n的数字分为长度为len和长度为1的块。将长度为1的块看作长度为len的块和其他块的分割区。
例如:len=2,n=6。11 | 2 | 564。
这样长度为len的块共有10种方式,长度为1的块共有9中方式,其他剩余的共有n-len-1位,即10^(n-len-1)。符合这样的位置的共有2个,即前端和后端。第一种sum_a=2 * 10 * 9 * 10^(n-len-1)。
-
我们将计算除了方式1以外的所有。
将剩余的划分为长度位len的块和两个长度位1的块。长度为1的块将放置在len的左面和右面。
例如:len=2,n=6。1 | 2 | 33 | 9 | 5 。len=2的块为33,2和9为长度为1的块。
这样的长度为len的块共有10种方式,长度为1的块共有9*9中方式,其他剩余的共有n-len-2位,即10^(n-len-2)。符合这样的位置共有( n-len-1) 个位置。第二种sum_b=(n-len-1) * 10 * 9 * 9 * 10^(n-len-2)。
总数为sum_a+sum_b。
ACcode:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const double PI = acos(-1.0);
const int maxn = 2e5 + 5;
const int mod = 998244353;
ll ten[maxn];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n;
ten[0] = 1;
cin >> n;
for (int i = 1; i <= n; i++)
ten[i] = (10 * ten[i - 1]) % mod;
for (int i = 1; i < n; i++) //按位置选择
{
ll a = (2 * 10 * 9 * ten[n - i - 1]) % mod; //首尾尾位置
ll b = ((n - i - 1) * 9 * 10 * 9 * ten[n - i - 2]) % mod; //中间位置
cout << (a + b) % mod << " ";
}
cout << 10 << endl;
return 0;
}