Codeforces 766 Div.2題解
Codeforces 766 Div.2題解
A
題意:給你一個矩陣,每一次操作你可以選擇一個字元為B的位置(x , y),可以使得x行字元都變為B,或者是讓y行字元都變成B
現在問你什麼情況下可以使 (x1,y1) 所在的位置字元為B
簡單分析一下:
①當(x1,y1)就是B的時候操作次數是0次
②當矩陣中不存在B的時候,不存在答案,為-1
③當x1行或者y1列存在B,那麼操作次數是1次
④否則,就需要兩次,從非x1行,非y1列的地方隨便操作一個B,可以使得x1行 or y1列中出現一個B,那麼就變成了③的情況,答案是2
檢視程式碼
#include<iostream> #include <vector> #include <cstring> #include <map> #include <algorithm> using namespace std; typedef long long ll; const int MAXN = 55; char a[MAXN][MAXN]; /* 4 10 1 0 3 4 8 5 8 3 6 */ void solve() { int n,m,x,y; scanf("%d %d %d %d",&n,&m,&x,&y); int f = 0; for(int i = 1;i <= n;++i) scanf("%s",a[i] + 1); for(int i = 1;i <= n;++i) for(int j = 1;j <= m;++j) { if(a[i][j] == 'B') { f = 1; break; } } if(!f) { puts("-1"); return ; } if(a[x][y] == 'B') { puts("0"); return ; } for(int i = 1;i <= n;++i) if(a[i][y] == 'B') { puts("1"); return ; } for(int i = 1;i <= m;++i) { if(a[x][i] == 'B') { puts("1"); return ; } } puts("2"); } int main() { int t = 1; scanf("%d",&t); while(t--) solve(); return 0; }
B
題意:
給你一個N * M的矩陣,Tina可以選擇其中的k個位置(k∈[0,n * m - 1]),使得這k個位置染色成為粉色,Rahul不會坐在粉色的位置,而Tina可以坐在任何的位置上。然後Rahul和Tina輪流選擇位置,Rahul想要最後同Tina坐的儘可能近,而Tina想要和他坐的儘可能遠,問你若他們兩個都非常聰明,k∈[0 , n * m - 1]這時候的最遠距離分別是多少
分析:
①由於k是在 0 ~ n * m - 1範圍之內的,那麼Rahul會將所有的位置都坐一遍
②由於Tina要坐的和Rahul儘可能的遠,那麼最優的情況就是選擇矩陣的四個角落(很簡單的貪心吧)
③K越大,Tina和Rahul的距離會盡可能的遠,也就是說答案是遞增的
那麼我們就可以將所有的位置都遍歷一遍,然後和四個角的哈密頓距離進行對比,取最大的那個,最後將陣列排序,輸出前n * m個數字即可
檢視程式碼
#include<iostream> #include <vector> #include <cstring> #include <map> #include <algorithm> using namespace std; typedef long long ll; const int MAXN = 55; char a[MAXN][MAXN]; /* 4 10 1 0 3 4 8 5 8 3 6 */ vector<int> ans; int dis(int x,int y,int x1,int y1) {return abs(x - x1) + abs(y - y1);} void solve() { ans.clear(); int n,m; scanf("%d %d",&n,&m); for(int i = 1;i <= n;++i) for(int j = 1;j <= m;++j) { ans.push_back(max(max(dis(i,j,1,1),dis(i,j,n,m)),max(dis(i,j,1,m),dis(i,j,n,1)))); } sort(ans.begin(),ans.end()); int siz = n * m - 1; for(int i = 0;i <= siz;++i) printf("%d%c",ans[i], " \n"[i == siz]); } int main() { int t = 1; scanf("%d",&t); while(t--) solve(); return 0; }
C
題意:
給你一棵樹,你要給所有的邊新增一個權值,使得每一個長度 <= 2的路徑權值和都是一個質數
分析:
我們可以直接看到第三個樣例,它為什麼不能夠構成一個Prime樹。
①分析可知,兩個非2的素數進行相加操作,得到的數字一定不是質數
②如果一個節點的度為3,那麼勢必需要存在兩個2,才可以使得其中的兩條邊和為質數,但是那兩條2的邊形成的不是質數,因此存在節點度數 >= 3的樹就直接輸出-1
③可以知道這顆樹是一個鏈,我們只需要從度數為0的點開始,依次對各條邊進行賦值即可(2,5,2,5,2,5,2....依次)
程式碼有點亂,可以看看正解的程式碼
檢視程式碼
#include<iostream>
#include <vector>
#include <cstring>
#include <map>
#include <algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 1e5 + 7;
bool prime[MAXN * 16 + 1];
int p[MAXN],top = 0;
/*
4 10 1
0 3 4 8
5 8 3 6
*/
vector<int> ans,tmp;
void ini()
{
top = 0;
int MAX = 1e6;
for(int i = 2;i < MAX;++i)
{
if(!prime[i]) p[++top] = i;
for(int j = 1;j <= top && 1ll * p[j] * i < MAX;++j)
{
prime[p[j] * i] = 1;
if(i % p[j] == 0) break;
}
}
}
struct node{
int x,id;
node(int x = 0,int id = 0):x(x),id(id){}
};
int deg[MAXN],a[MAXN];
vector<node> g[MAXN];
/*
1
6
3 4
4 5
5 6
2 1
2 3
*/
struct no{
int x,y,id;
}all[MAXN];
void dfs(int x,int fa,int ls)
{
for(int i = 0;i < g[x].size();++i)
{
node t = g[x][i];
if(t.x == fa) continue;
if(ls == 2)
a[t.id] = 5;
else
a[t.id] = 2;
dfs(t.x,x,a[t.id]);
}
}
void solve()
{
int n;
scanf("%d",&n);
for(int i = 1;i <= n;++i) deg[i] = 0,g[i].clear();
int f = 0;
for(int i = 1;i < n;++i)
{
int x,y;
scanf("%d %d",&x,&y);
deg[x] += 1;
deg[y] += 1;
g[x].push_back(node(y,i)),g[y].push_back(node(x,i));
all[i].id = i;
all[i].x = x,all[i].y = y;
if(deg[x] >= 3 || deg[y] >= 3) f = 1;
}
if(f)
{
puts("-1");
return ;
}
for(int i = 1;i <= n;++i)
{
if(deg[i] == 1)
{
for(int j = 1;j < n;++j)
{
if(all[j].x == i || all[j].y == i)
{
a[all[j].id] = 2;
dfs(i,0,2);
for(int j = 1;j < n;++j)
printf("%d%c",a[j]," \n"[j == n - 1]);
return ;
}
}
}
}
puts("-1");
}
int main()
{
// ini();
int t = 1;
scanf("%d",&t);
while(t--)
solve();
return 0;
}
D
題意:
n個數,每一次操作你可以選擇其中的兩個數進行GCD,然後將得到的數字加入到序列的末尾,當然這個數字不能出現在原序列當中,問你最多操作幾次。
分析:
①看到a的最值是1e6我們可以發現這裡面一定有貓膩,那麼我們可以每次對數字i進行判定,看看它能不能加入到我們的序列當中
②如果一個數能夠加入進來,那麼所有在序列中的數字能被這個數取餘為0的,進行GCD操作一定會得到這個數,具體來說就是:
最終的答案就是ans - n
檢視程式碼
#include <iostream>
#include <vector>
#include <cstring>
#include <map>
#include <algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 1e6 + 7;
bool vis[MAXN];
bool prime[MAXN];
int p[MAXN],top = 0;
void ini()
{
for(int i = 2;i < MAXN;++i)
{
if(!prime[i]) p[++top] = i;
for(int j = 1;j <= top && 1ll * p[j] * i < MAXN;++j)
{
prime[p[j] * i] = 1;
if(i % p[j] == 0) break;
}
}
}
/*
2
4 16
*/
int gcd[MAXN];
void solve()
{
int n;
scanf("%d",&n);
for(int i = 1;i <= n;++i) {
int x;
scanf("%d",&x);
vis[x] = 1;
}
int ans = 0;
for(int i = 1;i <= 1e6;++i)
{
for(int j = i;j <= 1e6;j += i)
if(vis[j]) gcd[i] = __gcd(gcd[i],j);
ans += gcd[i] == i;
}
printf("%d\n",ans - n);
}
int main()
{
// ini();
int t = 1;
// scanf("%d",&t);
while(t--)
solve();
return 0;
}