官方题解地址

https://codeforces.com/blog/entry/99067


EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEm.

A. Not Shading

分四种情况讨论:

  • 若第rr行第cc列的元素 (以下简称Ai,jA_{i,j}) 初始就是黑色,则需要操作00次。
  • 若第rr行或第cc列存在至少一个黑色格子,则需要操作11次。
  • n×mn × m的格子中存在至少一个黑色格子,则需要操作22次即可将n×mn × m的所有格子变成黑色。
  • n×mn × m的格子中不存在黑色格子,则无解。
//木の葉舞う所に,火は燃ゆる。
#include <iostream>
#include <sstream>
#include <cstdio>
#include <cstdlib>
#include <iomanip>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
#include <deque>
#include <stack>
#include <string>
#include <cstring>
#include <vector>
#include <cmath>
#include <bitset>
#include <ext/rope>
#include <unordered_set>
#include <unordered_map>
#define int long long
#define endl '\n'
#define inf 0x3f3f3f3f3f3f3f3f
#define debug printf("Hello World\n")
#define ios ios::sync_with_stdio(false)
using namespace __gnu_cxx;
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int mod1 = 1e9 + 7, mod2 = 998244353;
const double PI = 3.1415926535898, Ee = 2.718281828459;
const int dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0};
inline int read()
{
    int x = 0, f = 1;char ch = getchar();
    while (!isdigit(ch)) {if (ch == '-') f = -1; ch = getchar();}
    while (isdigit(ch)) {x = x * 10 + ch - 48; ch = getchar();}
    return x * f;
}
const int N = 100 + 10, M = 1e6 + 10;

char a[N][N];

void solve()
{
    int n, m, r, c; cin>>n>>m>>r>>c;
    for(int i = 1;i <= n;i ++) cin>>a[i] + 1;
    if(a[r][c] == 'B') cout<<0<<endl;
    else
    {
        for(int i = 1;i <= n;i ++)
            if(a[i][c] == 'B')
            {
                cout<<1<<endl;
                return;
            }
        for(int j = 1;j <= m;j ++)
            if(a[r][j] == 'B')
            {
                cout<<1<<endl;
                return;
            }
        for(int i = 1;i <= n;i ++) for(int j = 1;j <= m;j ++)
            if(a[i][j] == 'B')
            {
                cout<<2<<endl;
                return;
            }
        cout<<-1<<endl;
    }

}

signed main() {
    ios;
    int t = 1;  cin>>t;
    while (t--) solve();
    return 0;
}

B. Not Sitting

结论:无论RahulRahul事先坐在哪里,TinaTina之后都会坐在四边形的四个角之一以保证距离最远。

证明:略(提示:通常的做法是可以把二维曼哈顿距离分别看出两个一维数轴上的距离之和就可以轻而易举的得出该结论)

枚举每个四边形中每个格子到四个角的最长距离并计数最后从小到大依次输出即可。

//木の葉舞う所に,火は燃ゆる。
#include <iostream>
#include <sstream>
#include <cstdio>
#include <cstdlib>
#include <iomanip>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
#include <deque>
#include <stack>
#include <string>
#include <cstring>
#include <vector>
#include <cmath>
#include <bitset>
#include <ext/rope>
#include <unordered_set>
#include <unordered_map>
#define int long long
#define endl '\n'
#define inf 0x3f3f3f3f3f3f3f3f
#define debug printf("Hello World\n")
#define ios ios::sync_with_stdio(false)
using namespace __gnu_cxx;
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int mod1 = 1e9 + 7, mod2 = 998244353;
const double PI = 3.1415926535898, Ee = 2.718281828459;
const int dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0};
inline int read()
{
    int x = 0, f = 1;char ch = getchar();
    while (!isdigit(ch)) {if (ch == '-') f = -1; ch = getchar();}
    while (isdigit(ch)) {x = x * 10 + ch - 48; ch = getchar();}
    return x * f;
}
const int N = 2e5 + 10, M = 1e6 + 10;

int ans[N];

void solve()
{
    int n, m; cin>>n>>m;
    for(int i = 1;i <= n;i ++) for(int j = 1;j <= m;j ++)
            ans[max(abs(i - 1), abs(n - i)) + max(abs(j - 1), abs(m - j))] ++;
    for(int i = n / 2 + m / 2;i <= n + m - 2;i ++)
    {
        for(int j = 1;j <= ans[i];j ++) cout<<i<<" ";
        ans[i] = 0;
    }
    cout<<endl;
}

signed main() {
    ios;
    int t = 1;  cin>>t;
    while (t--) solve();
    return 0;
}

C. Not Assigning

结论11: 不存在三个以上素数两两之和均为素数

证明: 设三个素数分别为a,b,ca, b, c

  1. a=2a = 2, 则bb, ccaa的和为素数则bbcc必须是奇数,此时b+cb + c 为奇数 ++ 奇数 == 偶数且大于22所以不是素数。
  2. a=a = 奇素数,则bb, ccaa的和为素数则bbcc必须是偶数,此时b+cb + c 为偶数 ++ 偶数 == 偶数且大于22所以不是素数。

结论22: 符合题目条件的树只能是一条链

证明: 反证法: 若不是一条链的树,则必有一个结点度数deg3deg\geq3,当有33条边连接到一个结点时三条边的权值应均为素数且两两之和均为素数,由结论11可知这是不可能实现的。

判断是否有度数deg3deg\geq3的结点,若有则无解,否则一定是一条链,按照染色法给边逐一染色即可,任选一组可行解均可,我这里选的 2255.

//木の葉舞う所に,火は燃ゆる。
#include <iostream>
#include <sstream>
#include <cstdio>
#include <cstdlib>
#include <iomanip>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
#include <deque>
#include <stack>
#include <string>
#include <cstring>
#include <vector>
#include <cmath>
#include <bitset>
#include <ext/rope>
#include <unordered_set>
#include <unordered_map>
#define int long long
#define endl '\n'
#define inf 0x3f3f3f3f3f3f3f3f
#define debug printf("Hello World\n")
#define ios ios::sync_with_stdio(false)
using namespace __gnu_cxx;
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int mod1 = 1e9 + 7, mod2 = 998244353;
const double PI = 3.1415926535898, Ee = 2.718281828459;
const int dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0};
inline int read()
{
    int x = 0, f = 1;char ch = getchar();
    while (!isdigit(ch)) {if (ch == '-') f = -1; ch = getchar();}
    while (isdigit(ch)) {x = x * 10 + ch - 48; ch = getchar();}
    return x * f;
}
const int N = 2e5 + 10, M = 1e6 + 10;

vector<PII> e[N];
int deg[N];
int ans[N];
int num[2] = {2, 5};

void dfs(int u, int fa, int idx)
{
    for(auto &p : e[u])
    {
        int v = p.first, id = p.second;
        if(v == fa) continue;
        ans[id] = num[idx];
        dfs(v, u, 1 - idx);
    }
}

void solve()
{
    int n; cin>>n;
    for(int i = 1;i <= n;i ++) deg[i] = 0, e[i].clear();
    for(int i = 1;i < n;i ++)
    {
        int u, v; cin>>u>>v;
        e[u].push_back({v, i});
        e[v].push_back({u, i});
        deg[u] ++;
        deg[v] ++;
    }
    for(int i = 1;i <= n;i ++)
        if(deg[i] >= 3)
        {
            cout<<-1<<endl;
            return;
        }

    for(int i = 1;i <= n;i ++)
        if(deg[i] == 1)
        {
            dfs(i, 0, 0);
            break;
        }
    for(int i = 1;i < n;i ++) cout<<ans[i]<<" "; cout<<endl;
}

signed main() {
    ios;
    int t = 1;  cin>>t;
    while (t--) solve();
    return 0;
}

D. Not Adding

从大到小枚举每个数查询是否存在一组数的gcd等于该数,合法的一组数一定均为当前数的倍数。 枚举所有当前数的倍数求GCD的和,若该GCD和等于当前数,则当前数可加入列表中。

该题正确性证明请去看官方题解,Wo TCL。

//木の葉舞う所に,火は燃ゆる。
#include <iostream>
#include <sstream>
#include <cstdio>
#include <cstdlib>
#include <iomanip>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
#include <deque>
#include <stack>
#include <string>
#include <cstring>
#include <vector>
#include <cmath>
#include <bitset>
#include <ext/rope>
#include <unordered_set>
#include <unordered_map>
#define int long long
#define endl '\n'
#define inf 0x3f3f3f3f3f3f3f3f
#define debug printf("Hello World\n")
#define ios ios::sync_with_stdio(false)
using namespace __gnu_cxx;
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int mod1 = 1e9 + 7, mod2 = 998244353;
const double PI = 3.1415926535898, Ee = 2.718281828459;
const int dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0};
inline int read()
{
    int x = 0, f = 1;char ch = getchar();
    while (!isdigit(ch)) {if (ch == '-') f = -1; ch = getchar();}
    while (isdigit(ch)) {x = x * 10 + ch - 48; ch = getchar();}
    return x * f;
}
const int N = 1e6 + 10, M = 1e6 + 10;

bool vis[N];

int gcd(int x, int y)
{
    if(x % y == 0) return y;
    return gcd(y, x % y);
}

void solve()
{
    int n; n = read();
    for(int i = 1;i <= n;i ++) vis[read()] = true;
    int mx = 1e6, ans = 0;
    for(int i = mx;i >= 1;i --)
    {
        if(!vis[i])
        {
            int tot = 0;
            for(int j = i + i;j <= mx;j += i)
            {
                if(vis[j]) tot = gcd(tot, j);
            }
            if(tot == i) vis[i] = true, ans ++;
        }
    }
    printf("%lld\n", ans);
}

signed main() {
//    ios;
    int t = 1;  // cin>>t;
    while (t--) solve();
    return 0;
}

E. Not Escaping

不会。