A
题意
给一个数n,把他拆成a,b并且满足n=a+b,然后a,b互为质数也就是两个数的最大公约数为1,并且要求b-a尽可能的小,也就是a和b接近
思路
让a,从n/2开始,然后遍历就行,算出来b为n-a,判断a,b是否互质,如果互质输出就行,如果不互质,a就减减,继续
代码
#include<iostream>
using namespace std;
bool isrp(int a, int b)
{
if(a==1||b==1) // 两个正整数中,只有其中一个数值为1,两个正整数为互质数
return true;
while(1)
{ // 求出两个正整数的最大公约数
int t = a%b;
if(t == 0)
{
break;
}
else
{
a = b;
b = t;
}
}
if(b>1) return false;// 如果最大公约数大于1,表示两个正整数不互质
else return true; // 如果最大公约数等于1,表示两个正整数互质
}
int main()
{
int n;
cin>>n;
for(int i=n/2;i>=1;i--)
{
int b=n-i;
if(isrp(i,b))
{
cout<<i<<" "<<b;
break;
}
}
return 0;
}
B
题意
给你n个房子,然后给你k个人,意思是这n个房子有k个房子已经居住过了,k个人住哪k个房子是最不知道的
然后规定有邻居的就是优质房子,然后给你n和k的值问你优质房子的最大值和最小值
思路
首先k为0或者等于n时候最大值和最小值肯定都是0,然后当k>n/2时,每隔一个空放一个k肯定都能放满,剩下的都是优质房,所以最大值为n-k,如果k<n/2时,可以想象一下如果n尽可能的大,k尽可能的小,那么可以满足 每个k两边都是优质房,所以最大值为2k,但这样有的数值会使2k加k大于n了这样不符合意义,所以如果2k>n-k最大值得是n-k,小于时最大值为2k,只要k的值不为0最小值肯定是1,因为k可以从头并排着 只剩末尾一个优质房
代码
#include<iostream>
using namespace std;
int main()
{
int maxn;
int minn;
int n;int k;
cin>>n>>k;
if(k==n||k==0)
{
maxn=0;
minn=0;
}
else
{
if(k>=n/2)
{
minn=1;
maxn=n-k;
}
else
{
minn=1;
if(2*k>n-k)
maxn=n-k;
else
maxn=2*k;
}
}
cout<<minn<<" "<<maxn;
return 0;
}
C
题意
本来安排了n架飞机,每架飞机有mi的重要度,第i架飞机的起飞时间原定为i,而现在在k时之前不能有任何飞机起飞,每个时间点只有1架飞机能起飞,损失被定义为(飞机现起飞时间-飞机原起飞时间)*该飞机的重要度.现在要求你排一张时间表,要求每架飞机都只能在原起飞时间及以后起飞,且使损失最小.还要保证原定i起飞的飞机要在i之后起飞
思路
这题显然是重要度越大的越先起飞好,因为:假设a>b , an+b(n+1)=(a+b)n+b (1) , a(n+1)+b*n=(a+b)*n+a (2).显然(1)>(2).,但是这题还得保证原定i起飞的飞机要在i之后(或者i)起飞,所以我们还不能全部把所有单位都ya在优先队列里,
我们先把原定1-k时间的单位压到优先队列,然后,再把k+1到n+k依次压进一边加进原定当时起飞的飞机,一边找到优先队列中的最大值即队顶元素,将它放在该位置,更新它的新的起飞时间.这样可以保证i时进来的飞机一定在i之后起飞.
代码
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
struct NODE
{
int i,w;
bool operator < (const NODE&a)const
{
return w<a.w;
}//重载<运算法为了保证放入优先对列的时候是按w排序的
}p[300010];
int main()
{
int n,k;
cin>>n>>k;
for(int i=1;i<=n;i++)
{
cin>>p[i].w;
p[i].i=i;
}
priority_queue<NODE>q;
for(int i=1;i<=k;i++)
q.push(p[i]);
long long sum=0;
for(int i=k+1;i<=n+k;i++)
{
if(i<=n)
{
q.push(p[i]);
}
NODE now=q.top();
q.pop();
sum+=(long long) (i-now.i)*now.w;
p[now.i].i=i;
}
cout<<sum<<endl;
for(int i=1;i<=n;i++)
cout<<p[i].i<<" ";
return 0;
}
E
题意
这题实际上就是一个拆数问题,给你n个数,两个人拆,第一个人先拆,如果轮到一个人拆的时候这个数为1也就是不能再继续拆了 那么这个人就输了,但是每个数也都是轮换着的,假设第一个数 是第二个不能拆了 他输了 ,第二个数就由他现在拆
思路
因为一个数字n,可以拆的次数为固定的n-1次,故而只要统计全部的可操作次数,看总和的奇偶性即可。
代码
#include<iostream>
using namespace std;
int main()
{
int n;
int temp;
int sum=0;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>temp;
sum+=temp-1;
if(sum%2==0)
cout<<"2"<<endl;
else
cout<<"1"<<endl;
}
return 0;
}