A Two Regular Polygons
1 题目大意
给你两个正多边形,一个 $n$ 条边 $A$ ,一个 $m$ 条边 $B$
问 $B$ 有没有可能被 $A$ 包含且所有顶点都与 $A$ 的某一个节点重合
有输出 YES
,否则输出 NO
2 Code
判 $n \bmod m = 0$ 就可以了
#include <cstdio>
int T;
int n, m;
int main() {
scanf( "%d", &T );
while( T -- ) {
scanf( "%d%d", &n, &m );
printf( "%s\n", ( n % m == 0 )? "YES": "NO" );
}
}
B Bogosort
1 题目大意
给你一个长度为 $n$ 的序列 $a$, 你可以将 $a$ 重新排序,使其满足 $j – a_j \neq i – a_i$
输出任何一个即可
保证有解
$n \leq 100$
2 思路
$$
\begin{aligned}
j – a_j & \neq i – a_i \\
j – i & \neq a_j – a_i
\end{aligned}
$$
直接从大到小输出
3 Code
// Woshiluo Luo<[email protected]>
// 2020/03/09 22:40:32
#include <cstdio>
#include <cstring>
#include <algorithm>
template<class T>
T Min( T _a, T _b ) { return _a < _b? _a: _b; }
template<class T>
T Max( T _a, T _b ) { return _a > _b? _a: _b; }
template<class T>
T chk_Min( T &_a, T _b ) { return _a = (_a < _b? _a: _b); }
template<class T>
T chk_Max( T &_a, T _b ) { return _a = (_a > _b? _a: _b); }
const int N = 110;
int T;
int n;
int a[N];
int main() {
scanf( "%d", &T );
while( T -- ) {
scanf( "%d", &n );
for( int i = 1; i <= n; i ++ ) {
scanf( "%d", &a[i] );
}
std::sort( a + 1, a + n + 1 );
for( int i = n; i >= 1; i -- ) {
printf( "%d ", a[i] );
}
printf( "\n" );
}
}
C Adding Powers
1 题目大意
给你两个长度为 $n$ 的数列 $a,v$
其中 $a$ 通过输入提供,$v$ 初始所有值为 $0$
接下来,对于第 $i$ 次操作(从 $0$ 计数),你可以
- 选择任意一个 $v_i$ 增加 $k^i$
- 什么都不做
问你是否通过多次操作后,使 $v$ 变成 $a$
能输出 YES
,否则输出 NO
2 思路
首先对于每个数字 $a$, 考虑其是否可以变成多个 $k^i$ 的和(不能有重复的 $i$)
能的话算出来,看看有没有和之前重复的,有就不可能
不能的话直接没有可能
3 Code
// Woshiluo Luo<[email protected]>
// 2020/03/09 22:58:45
#include <cstdio>
#include <cstring>
#include <algorithm>
template<class T>
T Min( T _a, T _b ) { return _a < _b? _a: _b; }
template<class T>
T Max( T _a, T _b ) { return _a > _b? _a: _b; }
template<class T>
T chk_Min( T &_a, T _b ) { return _a = (_a < _b? _a: _b); }
template<class T>
T chk_Max( T &_a, T _b ) { return _a = (_a > _b? _a: _b); }
const int N = 110;
int T;
int n;
long long k;
bool vis[N];
long long a[N];
inline void wrong() {
printf( "NO\n" );
}
inline void right() {
printf( "YES\n" );
}
void calc() {
for( int i = 1; i <= n; i ++ ) {
if( a[i] == 0 ) {
continue;
}
long long cur = a[i];
int cnt = 1;
while( cur ) {
int tmp = cur % k;
if( tmp > 1 ) {
wrong();
return ;
}
if( tmp == 1 ) {
if( vis[cnt] == false )
vis[cnt] = true;
else {
wrong();
return ;
}
}
cur /= k;
cnt ++;
}
}
right();
}
int main() {
scanf( "%d", &T );
while( T -- ) {
memset( vis, 0, sizeof(vis) );
scanf( "%d%lld", &n, &k );
for( int i = 1; i <= n; i ++ ) {
scanf( "%lld", &a[i] );
}
calc();
}
}
D Count the Arrays
1 题目大意
你需要寻找这样的数列个数
- 有 $n$ 个元素
- 每个数字都是 $1$ 到 $m$ 之间的整数
- 只有恰好一对数字相等
- 数列先严格递增,再严格递减
个数对 $998244353$ 取模后输出
$2 \leq n \leq m \leq 2 \times 10^5$
2 思路
式子题,看 Code 去
3 Code
// Woshiluo Luo<[email protected]>
// 2020/03/09 23:21:18
#include <cstdio>
#include <cstring>
#include <algorithm>
template<class T>
T Min( T _a, T _b ) { return _a < _b? _a: _b; }
template<class T>
T Max( T _a, T _b ) { return _a > _b? _a: _b; }
template<class T>
T chk_Min( T &_a, T _b ) { return _a = (_a < _b? _a: _b); }
template<class T>
T chk_Max( T &_a, T _b ) { return _a = (_a > _b? _a: _b); }
const int N = 2e5 + 1e4;
const int mod = 998244353;
inline int add( int a, int b ) { return ( a + b ) % mod; }
inline int mul( int a, int b ) { return ( 1LL * a * b ) % mod; }
inline void add_eq( int &a, int b ) { a = ( a + b ) % mod; }
inline void mul_eq( int &a, int b ) { a = ( 1LL * a * b ) % mod; }
int ksm( int a, int p ) {
int res = 1;
while(p) {
if( p & 1 )
res = mul( res, a );
a = mul( a, a );
p >>= 1;
}
return res;
}
inline int get_inv( int a ) { return ksm( a, mod - 2 ); }
int n, m, sum, ans;
int fact[N], inv[N];
void init() {
fact[1] = 1;
for( int i = 2; i <= m; i ++ ) {
fact[i] = mul( fact[ i - 1 ], i );
}
inv[m] = get_inv( fact[m] );
for( int i = m - 1; i >= 1; i -- ) {
inv[i] = mul( inv[ i + 1 ], i + 1 );
}
inv[0] = 1;
fact[0] = 1;
}
// Get C^a_b
inline int C( int a, int b ) {
if( a <= 0 )
return 1;
if( b <= 0 )
return 1;
return mul( mul( fact[b], inv[ b - a ] ), inv[a] );
}
int main() {
#ifdef woshiluo
freopen( "d.in", "r", stdin );
freopen( "d.out", "w", stdout );
#endif
scanf( "%d%d", &n, &m );
init();
for( int i = n - 1; i <= m; i ++ ) {
add_eq( sum, mul( C( n - 3, i - 2 ), mul( m - i + 1, n - 2 ) ) );
}
for( int i = 2; i < n; i ++ ) {
add_eq( ans, mul( sum, C( i - 2, n - 3 ) ) );
}
printf( "%d\n", ans );
}
E Array Shrinking
1 题目大意
这好像是个原题
给你一个长度为 $n$ 的数列 $a$
如果 $a_i = a_{i + 1}$, 那么这两个数可以合并成 $a_i + 1$
问最小数列长度
$1 \leq a_i \leq 1000, 1 \leq n \leq 500$
2 思路
区间 dp
设 $f_{i,j}$ 为 $i$ 到 $j$ 最小长度
$merged_{i,j}$ 为 $i$ 到 $j$ 合并出来的数字
然后就是标准板子了
3 Code
// Woshiluo Luo<[email protected]>
// 2020/03/10 15:50:48
#include <cstdio>
#include <cstring>
#include <algorithm>
const int N = 510;
template<class T>
T Min( T _a, T _b ) { return _a < _b? _a: _b; }
template<class T>
T Max( T _a, T _b ) { return _a > _b? _a: _b; }
template<class T>
T chk_Min( T &_a, T _b ) { return _a = (_a < _b? _a: _b); }
template<class T>
T chk_Max( T &_a, T _b ) { return _a = (_a > _b? _a: _b); }
int n;
int a[N];
int f[N][N], merged[N][N];
int main() {
#ifdef woshiluo
freopen( "e.in", "r", stdin );
freopen( "e.out", "w", stdout );
#endif
scanf( "%d", &n );
for( int i = 1; i <= n; i ++ ) {
scanf( "%d", &a[i] );
f[i][i] = 1;
merged[i][i] = a[i];
}
for( int len = 2; len <= n; len ++ ) {
for( int left = 1, rig = len; rig <= n; left ++, rig ++ ) {
f[left][rig] = rig - left + 1;
for( int mid = left; mid < rig; mid ++ ) {
int &f_left = f[left][mid], &f_rig = f[ mid + 1 ][rig],
&merge_left = merged[left][mid], &merge_rig = merged[ mid + 1 ][rig];
chk_Min( f[left][rig], f_left + f_rig );
if( f_left == 1 && f_rig == 1 && merge_left == merge_rig ) {
f[left][rig] = 1;
merged[left][rig] = merge_left + 1;
}
}
}
}
printf( "%d\n", f[1][n] );
}