Codeforces Round #777 (Div. 2)
先吐槽一句,怎么会有人出阅读理解+分类讨论题啊。。。
A
给出一个数 \(n\),让你构造一个最大的数,使得这个数各位数字之和为 \(n\) 且不含 \(0\) 也没有两个相同的数相邻。那直接构造 \(12\) 交替就行了,分类一下模 \(3\) 的余数然后直接输出就行啦。
My Code
using namespace std;
void solve(){
int n;cin>>n;
if(n%3==0){
rep(i,1,n/3) cout<<"21";
cout<<'\n';
}else if(n%3==1){
cout<<"1";
rep(i,1,n/3) cout<<"21";
cout<<'\n';
}else{
cout<<"2";
rep(i,1,n/3) cout<<"12";
cout<<'\n';
}
}
int main()
{
ios::sync_with_stdio(0);
int T;
for(cin>>T;T--;)
solve();
return 0;
}
B
定义一个子矩阵是好的,当且仅当这个子矩阵内全是 \(1\) 并且不被其它任意一个全是 \(1\) 的矩阵包含。
定义一个矩阵是优雅的,当且仅当没有两个好的矩阵相交。
判断矩阵是不是好的。
考虑一个 \(2\times 2\) 的子矩阵内,如果 \(1\) 的个数是 \(4\) 的(也就是满的),那这一定只被一个好的矩阵包含。同样的只有 \(2\) 及以下个点也只能被一个好的矩阵包含(要不然就被最大的好的矩阵包含它就不好了)。但是如果是 \(3\) 的话,那在拐弯的地方那个格子会被包含 \(2\) 次。
所以扫一遍有没有 \(2\times 2\) 的矩阵内有 \(3\) 个 \(1\) 的。
My Code
using namespace std;
const int MAXN=110;
char mp[MAXN][MAXN];
void solve(){
int n,m;cin>>n>>m;
rep(i,1,n) rep(j,1,m) cin>>mp[i][j];
rep(i,1,n-1) rep(j,1,m-1){
int cnt=mp[i][j]-'0'+mp[i+1][j]-'0'+mp[i][j+1]-'0'+mp[i+1][j+1]-'0';
if(cnt==3){
cout<<"NO\n";
return;
}
}cout<<"YES\n";
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int T;for(cin>>T;T--;)
solve();
return 0;
}
C
每次可以选中一个子矩阵,并将其黑白染色(左上是白)。最初是空白的矩阵,求构造方案使得达到最终状态。
构造,我们能让任意的 \((x,y+1)\) 或者 \((x+1,y)\) 变成黑色并且不对别的产生影响,那只要判断一下 \((1,1)\) 是否是黑的,然后倒着填,每次填一个黑色格子就行了。
My Code
using namespace std;
const int MAXN=110;
struct opt{
int lx,ly,rx,ry;
};
int a[MAXN][MAXN],cur[MAXN][MAXN];
void solve(){
int n,m;cin>>n>>m;char c;
rep(i,1,n) rep(j,1,m) cin>>c,a[i][j]=c-'0',cur[i][j]=0;
if(a[1][1]){cout<<-1<<'\n';return;}
vector<opt> ans;
per(i,n,1) per(j,m,1){
if(cur[i][j]==a[i][j]) continue;
if(!a[i][j])
cur[i][j]=0,ans.pb((opt){i,j,i,j});
else{
if(j>1) cur[i][j]=1,cur[i][j-1]=0,ans.pb((opt){i,j-1,i,j});
else cur[i-1][j]=0,cur[i][j]=1,ans.pb((opt){i-1,j,i,j});
}
}cout<<(int)ans.size()<<'\n';
for(auto s:ans) cout<<s.lx<<' '<<s.ly<<' '<<s.rx<<' '<<s.ry<<'\n';
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int T;for(cin>>T;T--;)
solve();
return 0;
}
D
定义一个数是好数,当且仅当 \(d|a\) 且 \(d^2\nmid a\)。定义一个数是牛逼的当且仅当这个数有至少两种分解因数的方式,使得分解出来的都是好数。
求给出 \(x,d\) 后 \(x\) 是不是牛逼的。
令 \(x=kd^n\),\(n\) 取最大。然后开始分讨。(下面每个如果都在上面的如果不成立的前提下)
如果 \(n\le1\),那么显然不行。
如果 \(k\) 是合数,那么显然可以。
如果 \(d\) 是质数,那么显然不行。
如果 \(n<3\),那么显然不行。
如果 \(n>3\),那么显然可以。(就你随便拆一个 \(d\) 就行了)
如果 \(n=3\),那么把最后一个 \(d\) 拆开,枚举所有拆法,然后直接判断就行了。
My Code
#define int long long
using namespace std;
bool isp(int x){
if(x==1) return 1;
for(int i=2;i*i<=x;i++)
if(x%i==0) return 0;
return 1;
}
void solve(){
int x,d;cin>>x>>d;
int n=0;while(x%d==0) x/=d,n++;
if(n<2){cout<<"NO\n";return;}
if(!isp(x)){cout<<"YES\n";return;}
if(isp(d)){cout<<"NO\n";return;}
if(n>3){cout<<"YES\n";return;}
if(n<=2){cout<<"NO\n";return;}
for(int i=2;i*i<=d;i++){
if(d%i) continue;
int a=i,b=d/i;
if(x*a%d){
cout<<"YES\n";
return;
}
if(x*b%d){
cout<<"YES\n";
return;
}
}cout<<"NO\n";
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int T;for(cin>>T;T--;)
solve();
return 0;
}