文章目录
A - Your First Judge
签到题
#include <cstdio>
#include <iostream>
using namespace std;
string s;
int main() {
cin >> s;
if( s == "Hello,World!" ) printf( "AC\n" );
else printf("WA\n" );
return 0;
}
B - log2(N)
签到题
#include <cstdio>
int main() {
long long n;
scanf( "%lld", &n );
int ans;
for( int i = 0;;i ++ ) {
if( ( 1ll << i ) <= n ) ans = i;
else break;
}
printf( "%d", ans );
return 0;
}
C - One More aab aba baa
离散化后压成整数搜索,简单题
#include <stack>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
stack < char > sta;
char s[10], rnk[10];
int t[40325], used[30];
bool vis[10];
int n, k, cnt, tot;
void dfs( int x, int val ) {
if( x > n ) {
t[++ cnt] = val;
return;
}
for( int i = 1;i <= n;i ++ )
if( vis[i] ) continue;
else {
vis[i] = 1;
dfs( x + 1, val * 10 + used[s[i] - 'a' + 1] );
vis[i] = 0;
}
}
int main() {
scanf( "%s %d", s + 1, &k );
n = strlen( s + 1 );
for( char i = 'a';i <= 'z';i ++ )
for( int j = 1;j <= n;j ++ )
if( s[j] == i ) {
used[i - 'a' + 1] = ++ tot, rnk[tot] = i;
break;
}
dfs( 1, 0 );
sort( t + 1, t + cnt + 1 );
cnt = unique( t + 1, t + cnt + 1 ) - t - 1;
while( t[k] ) sta.push( rnk[t[k] % 10] ), t[k] /= 10;
while( ! sta.empty() ) printf( "%c", sta.top() ), sta.pop();
return 0;
}
D - Coprime 2
质因数分解后,把质因数的倍数都筛掉,简单题
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
#define maxn 100005
vector < int > ans;
int cnt;
bool vis[maxn], is[maxn];
int prime[maxn];
void init( int n ) {
for( int i = 2;i <= n;i ++ ) {
if( ! vis[i] ) is[i] = 1, prime[++ cnt] = i;
for( int j = 1;j <= cnt && i * prime[j] <= n;j ++ ) {
vis[i * prime[j]] = 1;
if( i % prime[j] == 0 ) break;
}
}
}
int n, m;
int a[maxn], p[maxn * 100];
int main() {
init( 1e5 );
scanf( "%d %d", &n, &m );
for( int i = 1;i <= n;i ++ )
scanf( "%d", &a[i] );
cnt = 0;
for( int i = 1;i <= n;i ++ ) {
for( int j = 1;j * j <= a[i];j ++ )
if( a[i] % j == 0 ) {
if( is[j] ) p[++ cnt] = j;
if( is[a[i] / j] ) p[++ cnt] = a[i] / j;
}
}
for( int i = 1;i <= m;i ++ ) vis[i] = 0;
sort( p + 1, p + cnt + 1 );
cnt = unique( p + 1, p + cnt + 1 ) - p - 1;
for( int i = 1;i <= cnt;i ++ )
for( int j = p[i];j <= m;j += p[i] )
vis[j] = 1;
for( int i = 1;i <= m;i ++ )
if( ! vis[i] ) ans.push_back( i );
printf( "%d\n", ans.size() );
for( int i = 0;i < ans.size();i ++ )
printf( "%d\n", ans[i] );
return 0;
}
E - Chain Contestant
只有 10 10 10种,符合状压
d p i , s , j : dp_{i,s,j}: dpi,s,j: 到 i i i为止出现字符的状态为 s s s,上一次出现的字符为 j j j(多加一种字符表示空)
-
不选 i i i
d p i , s , j + = d p [ i − 1 ] [ s ] [ j ] dp_{i,s,j}+=dp[i-1][s][j] dpi,s,j+=dp[i−1][s][j]
-
选 i i i,必须满足 i i i位置字符没出现过或上一次出现字符就是 i i i位置字符
d p [ i ] [ 1 < < t [ i ] ∣ s ] [ t [ i ] ] + = d p [ i ] [ 1 < < t [ i ] ∣ s ] [ t [ i ] ] + d p [ i − 1 ] [ s ] [ j ] dp[i][1 << t[i] | s][t[i]]+=dp[i][1 << t[i] | s][t[i]] + dp[i - 1][s][j] dp[i][1<<t[i]∣s][t[i]]+=dp[i][1<<t[i]∣s][t[i]]+dp[i−1][s][j]
简单题
#include <cstdio>
#define int long long
#define mod 998244353
#define maxn 1002
#define S 1 << 10
int n;
char s[maxn];
int t[maxn];
int dp[maxn][S][11];
signed main() {
scanf( "%lld %s", &n, s + 1 );
for( int i = 1;i <= n;i ++ ) t[i] = s[i] - 'A';
dp[0][0][10] = 1;
for( int i = 1;i <= n;i ++ )
for( int sta = 0;sta < S;sta ++ )
for( int j = 0;j <= 10;j ++ )
if( ! dp[i - 1][sta][j] ) continue;
else {
dp[i][sta][j] = ( dp[i][sta][j] + dp[i - 1][sta][j] ) % mod;
if( j == 10 )
dp[i][1 << t[i] | sta][t[i]] = ( dp[i][1 << t[i] | sta][t[i]] + dp[i - 1][sta][j] ) % mod;
else
if( ( 1 << t[i] & sta ) and j != t[i] ) continue;
else
dp[i][1 << t[i] | sta][t[i]] = ( dp[i][1 << t[i] | sta][t[i]] + dp[i - 1][sta][j] ) % mod;
}
int ans = 0;
for( int i = 0;i < S;i ++ )
for( int j = 0;j <= 10;j ++ )
if( i == 0 && j == 10 ) continue;
else ans = ( ans + dp[n][i][j] ) % mod;
printf( "%lld\n", ans );
return 0;
}
F - Dist Max 2
二分答案
将点按 x x x坐标排序
类似滑动窗口模拟
记录在满足 x x x坐标情况下的最大最小 y y y,判断是否有满足与现在枚举 i i i的 y y y距离不小于二分答案
简单题
#include <queue>
#include <cstdio>
#include <algorithm>
using namespace std;
#define maxn 200005
struct node { int x, y; }p[maxn];
queue < node > q;
int n;
int main() {
scanf( "%d", &n );
for( int i = 1;i <= n;i ++ ) scanf( "%d %d", &p[i].x, &p[i].y );
sort( p + 1, p + n + 1, []( node s, node t ) { return s.x < t.x; } );
int l = 0, r = 1e9, ans;
next :
while( l <= r ) {
int mid = l + r >> 1;
while( ! q.empty() ) q.pop();
int Min = 1e9, Max = 0;
for( int i = 1;i <= n;i ++ ) {
while( ! q.empty() ) {
if( q.front().x > p[i].x - mid ) break;
Min = min( Min, q.front().y );
Max = max( Max, q.front().y );
q.pop();
}
if( Min <= p[i].y - mid or Max >= p[i].y + mid ) {
ans = mid, l = mid + 1;
goto next;
}
q.push( p[i] );
}
r = mid - 1;
}
printf( "%d\n", ans );
return 0;
}
G - Colorful Candies 2
中档题
令
C
C
C表示不同的糖果颜色数,将
N
N
N颗糖果重新离散化颜色1,2,...,C
显然答案与具体糖果的颜色无关,只与每种颜色的个数有关,令 n i n_i ni表示颜色为 i i i的糖果个数
枚举每一轮要选择的糖果个数 K K K
对于每一种颜色,定义 X i X_i Xi,若选择糖果种有 i i i颜色, X i = 1 X_i=1 Xi=1,否则 X i = 0 X_i=0 Xi=0
则 K K K糖果中不同颜色种数可以表示为 ∑ i = 1 C X i \sum_{i=1}^CX_i ∑i=1CXi
所求期望为 E [ ∑ i = 1 C X i ] E\Big[\sum_{i=1}^CX_i\Big] E[∑i=1CXi],根据期望的线性可加性知道 = ∑ i = 1 C E [ X i ] =\sum_{i=1}^CE\Big[X_i\Big] =∑i=1CE[Xi]
一个颜色出现的期望很简单,出现的方案数
/
/
/总方案数,出现的方案数
=
=
=总方案数
−
-
−一次都没出现
E
[
X
i
]
=
(
N
K
)
−
(
N
−
n
i
K
)
(
N
K
)
E\Big[X_i\Big]=\frac{\binom{N}{K}-\binom{N-n_i}{K}}{\binom{N}{K}}
E[Xi]=(KN)(KN)−(KN−ni)
枚举
i
i
i又是
O
(
n
)
O(n)
O(n)的时间,再加上外层的
K
K
K枚举,时间
O
(
n
2
)
O(n^2)
O(n2)难以接受
发现其实如果有
x
x
x种颜色的个数都是
n
i
n_i
ni,那么这
x
x
x种颜色的期望可以
O
(
1
)
O(1)
O(1)计算
x
∗
(
N
K
)
−
(
N
−
n
i
K
)
(
N
K
)
x*\frac{\binom{N}{K}-\binom{N-n_i}{K}}{\binom{N}{K}}
x∗(KN)(KN)−(KN−ni)
那么不同个数就是
n
i
=
1
,
2
,
.
.
.
,
n_i=1,2,...,
ni=1,2,...,,又要满足
∑
n
i
=
N
\sum n_i=N
∑ni=N,所以可以知道上界就是根号级别
n
i
=
1
,
2
,
.
.
.
,
N
n_i=1,2,...,\sqrt N
ni=1,2,...,N
#include <map>
#include <cstdio>
using namespace std;
#define int long long
#define mod 998244353
#define maxn 50005
map < int, int > color, cnt;
int fac[maxn], inv[maxn];
int n;
int qkpow( int x, int y ) {
int ans = 1;
while( y ) {
if( y & 1 ) ans = ans * x % mod;
x = x * x % mod;
y >>= 1;
}
return ans;
}
void init() {
fac[0] = inv[0] = 1;
for( int i = 1;i <= n;i ++ )
fac[i] = fac[i - 1] * i % mod;
inv[n] = qkpow( fac[n], mod - 2 );
for( int i = n - 1;i;i -- )
inv[i] = inv[i + 1] * ( i + 1 ) % mod;
}
int C( int n, int m ) {
if( n < m ) return 0;
else return fac[n] * inv[m] % mod * inv[n - m] % mod;
}
signed main() {
scanf( "%lld", &n );
init();
for( int i = 1, x;i <= n;i ++ ) {
scanf( "%lld", &x );
color[x] ++;//颜色x的出现次数
}
for( auto it : color )
cnt[it.second] ++;//颜色出现次数为x的颜色个数
for( int i = 1;i <= n;i ++ ) {
int ans = 0;
for( auto it : cnt )
ans = ( ans + ( C( n, i ) - C( n - it.first, i ) + mod ) % mod * it.second ) % mod;
printf( "%lld\n", ans * qkpow( C( n, i ), mod - 2 ) % mod );
}
return 0;
}
后言:
H
H
H就是
F
W
T
FWT
FWT,atcoder-abc
很喜欢在最后考些鹅心算法模板,不想补了