A (签到,模拟)
题目大意:给定形成对联的规则,判断两行字符串是否形成对联。
根据题目要求模拟即可。
code:
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define ios std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
const int N=1e4+10;
string s[N],t[N];
int n;
bool check()
{
int a=s[n].size(),b=t[n].size();
int x=s[n][a-1]-'0',y=t[n][b-1]-'0';
if(x>=3&&x<=4&&y<=2) return 1;
return 0;
}
void work()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>s[i];
for(int i=1;i<=n;i++) cin>>t[i];
map<int,int> mp;
if(!check()) cout<<"NO"<<endl;
else {
for(int i=1;i<=n;i++){
int len=s[i].size();
int y=s[i][len-1]-'0';
if(y==3||y==4) y+=100;
mp[i]=y;
}
for(int i=1;i<=n;i++){
int len=t[i].size();
int y=t[i][len-1]-'0';
if(y==3||y==4) y+=100;
if(abs(mp[i]-y)<=1) {
cout<<"NO"<<endl;
return ;
}
}
cout<<"YES"<<endl;
}
}
signed main()
{
int t;
cin>>t;
while(t--) work();
return 0;
}
I (思维,简单分类讨论)
题目大意:有一个包含0~
2
m
2^m
2m-1的集合,从中选k个数,将k个数异或起来,保证其异或值为n. 问k最大可以是多少。
0~ 2 m 2^m 2m-1的所有数异或值为0(m>1),因此只需少异或上n这个数,即可让最终结果为n。注意m为1和n为0的情况。 简单分类讨论即可。
code:
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define ios std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define int long long
//head
const int N=1e4+10;
int p[N];
map<int,int> mp;
void work()
{
int m,n;
cin>>m>>n;
int ans=1LL<<m;
if(m==1){
if(n==0) cout<<1<<endl;
else cout<<2<<endl;
}
else if(n==0) cout<<ans<<endl;
else cout<<ans-1<<endl;
}
signed main()
{
//ios;
int t;
cin>>t;
while(t--) work();
return 0;
}
K (规律,推公式)
题目大意:找到前缀长度为k的序列中,连续1的数量的最大值。
思路:可以把序列写的长一点,可以发现最长连续1的数量存在规律,把公式推出即可。
code:
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define ios std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define int long long
//head
const int N=1e4+10;
int p[N];
int n;
map<int,int> mp;
void get()
{
int x=1;
for(int i=0;i<=32;i++){
p[i]=x;
x*=2;
}
int sum=0;
mp[1]=1;
for(int i=1;i<=32;i++){
sum+=i*p[i-1];
mp[sum]=i;
}
}
void work()
{
int n;
cin>>n;
if(n==1) {
cout<<0<<endl;
return ;
}
n--;
int ans=0;
for(auto x:mp){
if(n>=x.first){
ans=x.first;
//cout<<ans<<'*'<<endl;
}
}
if(n>=ans+1) cout<<mp[ans]+1<<endl;
else cout<<mp[ans]<<endl;
}
signed main()
{
//ios;
int t;
cin>>t;
get();
while(t--) work();
return 0;
}
C (贪心,构造)
比较有意思的一个题,给定0~9每个数位的个数,要求构造出一个整数,满足:1.不含前导0。 2. 相邻位的数字不能相同。3. 构造出的整数的值尽可能小。若不存在输出-1 。
思路:一个很明显的性质是当数量最多的那个数字(假设为k个),大于剩余的所有数字之和(设为m), 即k>m时,无解。我们贪心的想,尽可能把较小的数字放在前面。 即我们从小到大枚举当前要放哪一个数字,若无法放置,则循环到下一个数字,若所有数字都无法放了,就说明无解。
注意一些细节问题。
code:
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define ios std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define int long long
//head
const int N=1e5+10;
int cnt[N];
void work()
{
int sum=0;
int ma=0;
for(int i=0;i<=9;i++){
cin>>cnt[i];
sum+=cnt[i];
ma=max(ma,cnt[i]);
}
if(cnt[0]==1&&sum==1){
cout<<0<<endl;
return ;
}
int f=0;
vector<int> ans;
//cout<<ans.size()<<endl;
while(sum)
{
for(int i=0;i<=9;i++){//枚举取哪个数
if(i==0&&(int)ans.size()==0) continue;
if(!cnt[i]||((int)ans.size()&&ans.back()==i)) continue;
int x=0;
for(int j=0;j<=9;j++){//求出哪个数剩余最多
if(j==i){
if(cnt[j]-1>cnt[x]) x=j;
}
else {
if(cnt[j]>cnt[x]) x=j;
}
}
int m=sum-cnt[x];
if(x==i){
if(cnt[x]-1<=m) {
ans.push_back(i);
sum--; cnt[i]--;
f=1; break;
}
}
else {
if(cnt[x]<=m) {
ans.push_back(i);
sum--; cnt[i]--;
f=1; break;
}
}
}
if(f==0){
cout<<-1<<endl;
return ;
}
}
for(int i:ans) cout<<i;
cout<<endl;
}
signed main()
{
ios;
int t;
cin>>t;
while(t--) work();
return 0;
}
J (二分图染色,思维)
题目大意:给定一个n*m的矩阵,每个格子有个值,在不添加标记的情况下,相邻且值相同的格子将会被合并,若给一些格子添加标记后,则合并的条件是相邻,值相同,标记相同。问最少要添加几种标记,并且标记的数量最少,才能让每个格子都不会被合并。输出要添加标记的格子的坐标和其标记。
因为是相邻格子才会有可能被合并,因此可以发现最多两种标记即可,可把整个矩阵染成黑白两种颜色。在染色过程中看哪个颜色的格子的数量较少,将其添加到答案中去。
code:
#include<bits/stdc++.h>
using namespace std;
#define x first
#define y second
#define int long long
typedef pair<int,int> pii;
const int N=1e3+10;
int a[N][N];
int dx[]={1,0,-1,0},dy[]={0,1,0,-1};
bool st[N][N];
vector<pii> ans;
int n,m;
struct node{
int x,y,c;
};
void bfs(int sx,int sy)
{
vector<pii> v1,v2;
queue<node> q;
q.push({sx,sy,0});
v1.push_back({sx,sy});
st[sx][sy]=1;
while(q.size())
{
auto t=q.front(); q.pop();
for(int i=0;i<4;i++){
int ex=t.x+dx[i],ey=t.y+dy[i];
if(ex>n||ex<1||ey>m||ey<1||st[ex][ey]) continue;
if(a[t.x][t.y]!=a[ex][ey]) continue;
st[ex][ey]=1;
if(t.c==0) v2.push_back({ex,ey});
else v1.push_back({ex,ey});
q.push({ex,ey,t.c^1});
}
}
if(v1.size()<v2.size()){
for(auto v:v1) ans.push_back(v);
}
else {
for(auto v:v2) ans.push_back(v);
}
}
void work()
{
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++) cin>>a[i][j];
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(!st[i][j]){
bfs(i,j);
}
}
}
if(ans.size()==0) {
cout<<"0 0"<<endl;
return ;
}
cout<<1<<' '<<ans.size()<<endl;
for(auto v:ans) cout<<v.x<<' '<<v.y<<' '<<1<<endl;
}
signed main()
{
int t;
t=1;//cin>>t;
while(t--) work();
return 0;
}