A.Two Regular Polygons
题意:
给定t组数据,每组给定一个正n边形和正m边形(m<n),询问是否能在正n边形中找到正m边形,即两个正多边形的顶点是否能完全重合。
题解:
因为n>m,只要判断n%m是否为0即可
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int maxn = 5e5 + 5;
const int INF = 0x3f3f3f3f;
const int mod = 998244353;
void solve()
{
int n, m;
scanf("%d%d", &n, &m);
if (n % m == 0)
puts("YES");
else
puts("NO");
}
int main()
{
int t;
for (scanf("%d", &t); t >= 1; t--)
solve();
}B.Bogosort
题意:
给一组数组,要求排序,使得任意i,j,i-a[i]!=j-a[j]
题解:
将数组从大到小排序就能满足条件
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int maxn = 5e5 + 5;
const int INF = 0x3f3f3f3f;
const int mod = 998244353;
int a[105];
void solve()
{
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++)
scanf("%d", &a[i]);
sort(a, a + n, greater<int>());
for (int i = 0; i < n; i++)
printf("%d ", a[i]);
puts("");
}
int main()
{
int t;
for (scanf("%d", &t); t >= 1; t--)
solve();
}C.Adding Powers
题意:
给定一个n个元素的数组,要求判断是否能由一个全为0的数组,加上k的i次(i=1,2,3,4…)相加得到,并且i不能重复
题解:
把每个数拆成k 进制。依题意,每一位至多是1,否则就不行
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int maxn = 5e5 + 5;
const int INF = 0x3f3f3f3f;
const int mod = 998244353;
int add[70];
void solve()
{
memset(add, 0, sizeof(add));
int n, k;
scanf("%d%d", &n, &k);
int f = 0;
for (int i = 0; i < n; i++)
{
ll x;
scanf("%lld", &x);
int j = 0;
while (x)
{
add[j] += (x % k);
if (add[j] > 1)
{
f = 1;
break;
}
x /= k;
j++;
}
}
if (f)
puts("NO");
else
puts("YES");
}
int main()
{
int t;
for (scanf("%d", &t); t >= 1; t--)
solve();
}D.Count the Arrays
题意:
构造一个长度为n的数组,值的范围1~m的数组,满足下面条件
1.数组中只能且必须出现一对相同的数字
2.先递增再递减
输出所有的构造方案数量
题解:
有且只有两个数相等,所以每个数组有n-1的数,从m中取n-1个数有C(m,n-1)种,只要将最大的数放在中间剩余的n-2个数只要分成两组放在两边即可,每个数都能放在左右两边,为了防止出现数全在一边的情况可以每次取出一个数放在右边,如果剩下的数全出现在左边也满足条件,因为有对称性所以成立,总共为。所以最终答案为
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int maxn = 2e5 + 5;
const int INF = 0x3f3f3f3f;
const int mod = 998244353;
ll fac[maxn];
ll qpow(ll a, ll b)
{
int res = 1;
while (b)
{
if (b & 1)
res = res * a % mod;
a = a * a % mod;
b >>= 1;
}
return res;
}
void init()
{
fac[0] = 1;
for (int i = 1; i < maxn; i++)
fac[i] = fac[i - 1] * i % mod;
}
ll c(int x, int y)
{
return fac[x] * qpow(fac[y] * fac[x - y] % mod, mod - 2) % mod;
}
int main()
{
init();
int n, m;
scanf("%d%d", &n, &m);
if (n == 2)
{
puts("0");
return 0;
}
printf("%lld\n", ((c(m, n - 1) * qpow(2, n - 3)) % mod * 1ll * (n - 2)) % mod);
return 0;
}E.Array Shrinking(DP)
题意:
给定一组长度为n的序列,每次可以将相邻的两个相等元素,即ai==a(i+1) ,合并成一个新的元素,其值为 ,询问经过多次操作后数组最小长度
题解:
首先可以 的预处理出所有可以合并的情况用,a[i][j]表示原先数组的[i,j]的数最终会合并成的数的值。dp[i]表示[1~i]中最多能合并的数个数,所以最终答案就是n-dp[n]。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int maxn = 505;
const int INF = 0x3f3f3f3f;
const int mod = 998244353;
int n, a[maxn][maxn], dp[maxn];
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i][i]);
for (int i = n; i; i--)
for (int j = i + 1; j <= n; j++)
for (int k = i; k < j; k++)
if (a[i][k] && a[i][k] == a[k + 1][j])
a[i][j] = a[i][k] + 1;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= i; j++)
if (a[j][i])
dp[i] = max(dp[i], dp[j - 1] + i - j);
cout << n - dp[n];
}
京公网安备 11010502036488号