题意:有两个集合 A A A, B B B。给出它们当中的元素,让你求两个数 x , y x,y x,y,使得 x ∈ A , y ∈ B x \in A, y \in B x∈A,y∈B且 x + y ∉ A , x + y ∉ B x+y \notin A, x+y \notin B x+y∈/A,x+y∈/B。
思路:用一个bool数组记录一下就可以了。
#include <bits/stdc++.h>
using namespace std;
int n,m,a[105],b[105];
bool p[405];
int main(){
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i],p[a[i]]=1;
cin>>m;
for(int i=1;i<=m;i++) cin>>b[i],p[b[i]]=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(!p[a[i]+b[j]]){
cout<<a[i]<<" "<<b[j]<<endl;
return 0;
}
}
}
return 0;
}
也可以直接输出它们的最大值。
#include <bits/stdc++.h>
using namespace std;
int n,m,a[105],b[105],mx1,mx2;
int main(){
cin>>n;for(int i=1;i<=n;i++) cin>>a[i];
cin>>m;for(int i=1;i<=m;i++) cin>>b[i];
cout<<*max_element(a+1,a+1+n)<<" "<<*max_element(b+1,b+1+m)<<endl;
}
1206B - Make Product Equal One
题意:有 n n n个数,每一次操作可以选择任意一个元素并将其 + 1 +1 +1或 − 1 -1 −1,问最少经过多少次操作才能使所有数的乘积为 1 1 1。
思路:贪心,每个数优先选择变成距离 − 1 -1 −1和 1 1 1中距离自己近的,然后统计 1 1 1的个数,如果是奇数将代价最小的 − 1 -1 −1变为 1 1 1.注意,再上一步,答案不能直接 + 2 +2 +2, 0 0 0要特殊处理。
#include <bits/stdc++.h>
using namespace std;
#define int long long
int n,a[100005],cnt,ans;
signed main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
int dist1=abs(-1-a[i]);
int dist2=abs(1-a[i]);
if(dist1<dist2){
cnt++;
ans+=dist1;
}
else{
ans+=dist2;
}
}
if(cnt%2==0){
cout<<ans<<endl;
}
else{
int mn=LLONG_MAX;
for(int i=1;i<=n;i++){
int dist1=abs(-1-a[i]);
int dist2=abs(1-a[i]);
if(dist1<=dist2){
mn=min(mn,dist2-dist1);
}
}
cout<<ans+mn<<endl;
}
return 0;
}
题意:给你一个 n n n,构造一个长度为 2 n 2n 2n的环,有 1 1 1至 2 n 2n 2n组成,使环上每 n n n个连续的点的记录下来。其中这些数要求只有2个数字构成,并且这两个数必须连续。问是否能满足要求并给出方案。
思路:由于这个长度为 2 n 2n 2n的环和为 S = n ( 2 n + 1 ) S=n(2n+1) S=n(2n+1),因此 S S S是偶数时,无解。当 S S S是奇数时,有解。
考虑如何构造,我们设答案数组为 a n s ans ans,那么我们先令 a n s 1 = 1 ans_1=1 ans1=1, a n s n + 1 = 2 ans_{n+1}=2 ansn+1=2,然后每一次,我们进行如下操作:
第一步: a n s 2 = 3 , a n s n + 2 = 4 , a n s n + 3 = 5 , a n s 3 = 6 ans_2=3,ans_{n+2}=4,ans_{n+3}=5,ans{3}=6 ans2=3,ansn+2=4,ansn+3=5,ans3=6。
第二步: a n s 4 = 7 , a n s n + 4 = 8 , a n s n + 5 = 9 , a n s 5 = 10 ans_4=7,ans_{n+4}=8,ans_{n+5}=9,ans{5}=10 ans4=7,ansn+4=8,ansn+5=9,ans5=10。
等等,以此类推。
时间复杂度 O ( n ) O(n) O(n)。
#include <bits/stdc++.h>
using namespace std;
#define int long long
int n,a[200005],cnt=0;
signed main(){
cin>>n;
if(n%2==0) return puts("NO"),0;
puts("YES");
for(int i=n,j=2*n,k=2*n;i>0;){
a[i]=k;a[j]=k-1;
if(i-1>0){
a[j-1]=k-2;a[i-1]=k-3;
}
i-=2;j-=2;k-=4;
}
for(int i=1;i<=2*n;i++) cout<<a[i]<<" ";
return 0;
}
题意:有 n n n个数 a 1 , a 2 , a 3 , … , a n a_1,a_2,a_3,\dots,a_n a1,a2,a3,…,an。已知如果两个数 a i , a j ( i ≠ j ) a_i,a_j (i \neq j) ai,aj(i̸=j)满足 a i a n d a j ≠ 0 a_i\ and\ a_j \neq 0 ai and aj̸=0(其中 a n d and and操作为按位与操作),那么在 i i i号节点与 j j j号节点间连一条边,求所构成的图的最小环的长度。
思路:首先,我们明白,这张图要么没有环,要么最小环的长度大于等于 3 3 3,因此,对于二进制下的每一位,只要有一位在 3 3 3个及以上个数的二进制表示下为 1 1 1,那么答案一定为 3 3 3。
因为每个数都小于 1 0 18 10^{18} 1018,因此每个数最多有 60 60 60位,因此如果有超过 120 120 120个非零数字,那么必定有一位在 3 3 3个及以上个数的二进制表示下为 1 1 1。
考虑没有任何一位在 3 3 3个及以上个数的二进制表示下为 1 1 1的情况,我们暴力连边,然后跑 F l o y d Floyd Floyd求最小环。因为最大只有 120 120 120个非零数字,所以时间复杂度最大为 O ( 12 0 3 ) O(120^3) O(1203)。
总的时间复杂度 O ( n l o g 1 0 18 + 12 0 3 ) O(n\ log 10^{18}+120^3) O(n log1018+1203)。
#include <bits/stdc++.h>
using namespace std;
#define int long long
int n,a[100005],b[100005],dist[130][130],s[130][130],ans=LLONG_MAX,cnt;
signed main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
if(a[i]!=0) b[++cnt]=a[i];
}
for(int i=1;i<=60;i++){
int cnt=0;
for(int j=1;j<=n;j++){
if(a[j]>>(i-1)&1){
cnt++;
}
}
if(cnt>=3){
puts("3");
return 0;
}
}
for(int i=1;i<=cnt;i++)
for(int j=1;j<=cnt;j++){
if(i!=j&&((b[i]&b[j])!=0)) s[i][j]=1,dist[i][j]=1;
else dist[i][j]=s[i][j]=0x3f3f3f3f;
}
for(int k=1;k<=cnt;k++){
for(int i=1;i<k;i++)
for(int j=i+1;j<k;j++)
ans=min(dist[i][j]+s[i][k]+s[k][j],ans);
for(int i=1;i<=cnt;i++)
for(int j=1;j<=cnt;j++)
dist[i][j]=min(dist[i][k]+dist[k][j],dist[i][j]);
}
cout<<((ans>=0x3f3f3f3f)?-1:ans)<<endl;
}