Codeforces Round 747 div.2 A-E
本文最后更新于:2 年前
A. Consecutive Sum Riddle
题意:给定一个 $n$,要找出 $l,r$ 使得 $\sum_{i=l}^{r}i=n$
解:显然,从 $-n+1$ 加到 $n$ 即可
void solve(){
ll n;
cin >> n;
cout << -n+1 << ' ' << n << '\n';
}
B. Special Numbers
题意:找第 $k$ 个 $n$ 好数,$n$ 好数就是可以被 $n$ 的不同次幂组成,比如 $n^0+n^2…$ 的方式表示
解:把 $k$ 转化为二进制,然后每一位按照 $n$ 的次幂加权计算即可
void solve(){
ll n, k;
cin >> n >> k;
ll ans = 0, t = 1;
while(k > 0){
if(k & 1){
ans = (ans + t) % mode;
}
k >>= 1;
t = t * n % mode;
}
cout << ans << '\n';
}
C. Make Them Equal
题意:给出一个字符串 $s$ 和字符 $c$,可以进行若干次操作,每次操作可以选择一个数 $x$,然后令字符串中所有下标不能被 $x$ 的整除的位置上的字符变成 $c$,问最少多少次操作可以使字符串全变成 $c$
解:由于 $n>2$,两次操作分别选择 $n$ 和 $n-1$ 一定可以完成,那么只需要考虑能不能一次完成
一次完成要求存在一个数 $x$,串中所有可以被 $x$ 整除的位置上都已经是 $c$ 了,暴力枚举即可,复杂度比较玄学但它就是 $nlogn$
后来又听了无敌的会长的优化方案:只需要枚举 $n/2$ 以上的 $x$ 即可,因为更小的 $x$ 总有一个倍数比它更优,复杂度 $2n$
void solve(){
int n;
char c;
string s;
cin >> n >> c >> s;
s = "0" + s;
for(int i=1;i<=n;i++){
bool flg = true;
for(int j=i;j<=n;j+=i){
if(s[j] != c){
flg = false;
break;
}
}
if(flg){
if(i == 1){
cout << "0\n";
return;
}
cout << 1 << '\n';
cout << i << '\n';
return;
}
}
cout << 2 << '\n';
cout << n-1 << ' ' << n << '\n';
}
D. The Number of Imposters
题意:有 $n$ 个人和 $m$ 个陈述,每个陈述形如:$i,j,imposter/crewmate$ 表示 $i$ 说 $j$ 是说真话的人/说谎者,问说谎话的人最多有几个
解:注意到一个性质:如果 $i$ 说 $j$ 说的是谎话,那么 $i$ 和 $j$ 必定相反;如果 $i$ 说 $j$ 说的是真话,那么 $i$ 和 $j$ 相同。
那么每个陈述都可以转化为一条边,对每个联通块进行染色后取较多的颜色加入贡献即可
int st[maxn];
struct Edge{
int t, nt, tp;
}e[maxn << 1];
int head[maxn], ecnt = 0;
inline void add(int x, int y, int tp){
e[++ecnt].t = y;
e[ecnt].tp = tp;
e[ecnt].nt = head[x];
head[x] = ecnt;
}
int num[2];
bool dfs(int p){
for(int i=head[p];i;i=e[i].nt){
int v = e[i].t;
if(st[v] == -1){
st[v] = st[p] ^ e[i].tp;
num[st[v]]++;
if(!dfs(v)) return false;
}else{
if(st[v] != (st[p] ^ e[i].tp)) return false;
}
}
return true;
}
void solve(){
int n, m;
cin >> n >> m;
ecnt = 0;
for(int i=1;i<=n;i++){
head[i] = 0;
st[i] = -1;
}
for(int i=1;i<=m;i++){
int x, y; string s;
cin >> x >> y >> s;
int tp = (s[0] == 'i');
add(x, y, tp);
add(y, x, tp);
}
int ans = 0;
for(int i=1;i<=n;i++){
if(st[i] == -1){
st[i] = 1;
num[1] = 1;
num[0] = 0;
if(!dfs(i)){
cout << "-1\n";
return;
}
ans += max(num[0], num[1]);
}
}
cout << ans << '\n';
}
E1. Rubik’s Cube Coloring (easy version)
题意:给一颗 $k$ 层的完全二叉树,每个节点有一个颜色(共六种),要求每个节点和其相邻节点颜色不能相同,并且规定了三对不能相邻的颜色,问有多少中染色方案
解:答案为 $4^{2^n-2}\times 6$
ll qpow(ll x, ll p){
ll r = 1;
while(p > 0){
if(p & 1) r = r * x % mode;
x = x * x % mode;
p >>= 1;
}
return r;
}
void solve(){
int n;
cin >> n;
cout << qpow(4, (1ll << n) - 2) * 6 % mode << '\n';
}