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;
}
}