2023牛客多校3

A World Fragments I

题意:

给出两个二进制数x,y,你可以从x中选一个数字b,可以让y+b或y-b,求最少多少操作次数可以让y等于x,输出操作次数,若无法将y变成x,则输出-1。

题解:

只有b=1时,操作才有意义,且每次可以让y+1或y-1,所以最小操作次数刚好是abs(x-y),特判一下x=0&&y!=0情况。

#include<iostream>
#include<algorithm>
#include<cstring>

#define int long long
using namespace std;

int change(string s)
{
	int radix=2;
    int ans = 0;
    for(int i = 0;i < s.size();i ++)
    {
        char t = s[i];
        if(t >= '0' && t <= '9') ans = ans * radix + (t - '0');
        else ans = ans * radix + t - 'a' + 10;
    }
    return ans;
}
signed main()
{
	string x,y;
	
	cin>>x>>y;
	
	if(x=="0"&&y!="0") cout<<"-1"<<endl;
	else cout<<abs(change(x)-change(y))<<endl;
	
	return 0;
}

D-Ama no Jaku

题意:

给定一个n*m的01矩阵A,A的第i行从左到右依次连接,形成可能带有前导零的二进制数r_{i},A的第j列从上到下依次连接,形成一个可能含有前导零的二进制数c_{j},每次操作可以将A指定的一行或一列进行反转,问能达到min(r_{i})>=max(c_{j})的最少操作次数。

题解:

该最小次数就是将A变为全是1或全是0的最小次数。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>

using namespace std;

int main()
{
	int n;
	
	scanf("%d",&n);
	
	vector<string> a(n);
	for(int i=0;i<n;i++) cin>>a[i];
	
	string s;
	int s1=0,s2=0;
	for(int i=0;i<n;i++)
	{
		s+=a[0][i]^1;//第一行反转的结果 
		s1+=(a[0][i]=='0');//第一行0的个数 
		s2+=(a[i][0]=='0');//第一列0的个数 
	 }
	 for(int i=0;i<n;i++)
	 	if(a[i]!=s&&a[i]!=a[0])
	 	{
	 		printf("-1\n");
	 		return 0;
		 } 
	printf("%d",min(n-s1,s1)+min(n-s2,s2));
	
	return 0;
}

H-Until the Blue Moon Rises

题意:

给定n个数,可选择两个数,一个加 1 另一个减 1 ,可以任意次操作,问是否可以将这n个数全变为质数。

题解:

记res为n个数的和,因为可以任意选择两个数,所以就是将res重新分配。
当n=1
直接判断res是否为质数。
当n=2
res为偶数,由哥特巴赫猜想,任意一个大于2的偶数都可以写成两个质数的和。
res为奇数,只能分成一个偶数和一个奇数,偶数必定为2,所以只需要判断res-2是否为质数。
当n>=3时
给前n-2个数都分配2,若剩余的和为奇数,则给第n-2个数分配3,此时剩余的数的和为偶数,再根据哥德巴赫猜想判断。

#include<iostream>
#include<algorithm>

#define int long long
using namespace std;

bool isprime(int x) {
    if (x<2) return false;
    for (int i = 2; i <= x / i; i ++)
        if (x % i == 0) return false;
    return true;
}

bool solve()
{
	int n;
	int x;
	cin>>n;
	
	int res=0;
	for(int i=0;i<n;i++)
	{
		cin>>x;
		res+=x;
	}
	if(n==1)
	{
		if(isprime(res)) return true;
		else return false;
	}
	if(n==2)
	{
		if(res%2)
		{
			if(isprime(res-2)) return true;
			else return false;
		}
		else
		{
			if(res>2) return true;
			else return false;
		}
	}
	else
	{
		if(res>=2*n) return true;
		else return false;
	}
}
signed main()
{
	if(solve()) cout<<"Yes"<<endl;
	else cout<<"No"<<endl;
	
	return 0;
}

J-Fine Logic

题解:

n个人,给出了m个其中两人的先后关系,求至少需要多少个排行榜才能使得适应关系成立一次,并输出他们总的先后关系。

题解:

若关系存在环就正序和逆序输出,否则输出拓扑序。

Tag:

拓扑排序

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>

using namespace std;
const int N=1e6+10;
int n,m;
vector<int>g[N];
vector<int>ans;
int deg[N];
int main()
{
   scanf("%d %d",&n,&m);
   for(int u,v,i=1;i<=m;i++)
   {
      scanf("%d %d",&u,&v);
      g[u].push_back(v);
      deg[v]++;
   }
   for(int i=1;i<=n;i++)
   {
      if(!deg[i])
      ans.push_back(i);
   }
   for(int i=0;i<ans.size();i++)
   {
      int cur=ans[i];
      for(int j=0;j<g[cur].size();j++)
      {
         if(!--deg[g[cur][j]])
         ans.push_back(g[cur][j]);
      }
   }
   if(ans.size()==n)
   {
      printf("1\n");
      for(int i=0;i<n;i++)
      printf("%d ",ans[i],i==n-1?'\n':' ');
   }
   else{
      printf("2\n");
      for(int i=1;i<=n;i++) printf("%d ",i);
      cout<<endl;
      for(int i=n;i>=1;i--) printf("%d ",i);
      cout<<endl;
   }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值