cf #681 Div. 2 A B C

A题 题目链接

题目大意
幼儿园有n个小朋友,4n个座位(从1号开始,4n号结束),我们需要帮助小朋友排座位,不符合要求的座位安排:
1.gcd(a,b)=1 (任意两个小朋友的座位号的最大公约数不能等于1)
2.a%b=0或b%a=0(任意两个小朋友的座位号不能被对方整除)

输入
第一行为正整数t(1≤t≤100)——测试用例数。
每个测试用例包含一行包含整数n(1≤n≤100)——孩子的数量。

输出
输出t行,它包含从1到4n的n个不同的整数——孩子们在相应的测试用例中应该占据的椅子的数量。如果有多个答案,打印任意一个。你可以按任何顺序打印n个数字。

解题思路
我们需要输出n个数字,代表n个小朋友的座位号。座位号的范围是1~4n,对于n个小朋友只要坐在 4n 4n-2 4n-4 … 4n-2*(n-1) 这n个位置上就一定满足题目要求。
对于第一个要求gcd(a,b)!=1 输出的所有座位号都是2的倍数,所以最小的公约数为2>1,符合要求。
对于第二个要求a%b!=0或b%a!=0 输出中最大的座位号为4n,4n最大的因数为2n,随着座位号减少对应的最大因数也会减小,所以我们只需证明 2n<4n-2*(n-1) 即可,即证 2n<2n+2 ,0<2,得证。

/*题目样例*/
input
3
2
3
4
output
6 4
4 6 10
14 10 12 8
/*A*/
#include<bits/stdc++.h>
using namespace std;
int main(){
	int t,n;
	scanf("%d",&t);
	for(int i=1;i<=t;i++){
		scanf("%d",&n);
		for(int j=0;j<n;j++){
			printf("%d ",4*n-2*j);
		}
		printf("\n");
	}
	return 0;
}

B题 题目链接

题目大意:
一个城市有n个建筑物,一些建筑下埋有地雷,给出这个城市的地图——由0和1组成的字符串,如果第i个字符是1那么第i个建筑物下存有地雷,反之若第i个建筑物下没有地雷,则第i个字符为0。
当编号为x的建筑物下的地雷被激活时,它会爆炸并激活编号为x-1和x+1的建筑物下的两个相邻地雷(如果建筑物下没有地雷,则不会发生任何事情)。因此,在一个连续的地雷段上激活任何一枚地雷就足以激活该段的所有地雷。为了激活一枚地雷,士兵需要花费a枚硬币(可重复操作),如果一个建筑物下没有地雷,士兵可以在那里放置地雷,每次操作会花费b枚硬币(可重复操作),两种行为均没有顺序要求。
士兵想要激活所有地雷,并花费最少的硬币。

输入
第一行为正整数t(1≤t≤1e5)——测试用例数。
每个测试用例以一行包含两个整数a和b (1≤a,b≤1000)——分别是激活和放置一枚地雷的成本。
下一行包含一张城市的地图——一个由0和1组成的字符串。
所有测试用例的字符串长度总和不超过1e5。

输出
对于每个测试用例,输出一个整数——士兵必须支付的最小硬币数。

解题思路
对于字符串中的每个地雷1,我们只需要判断激活它所需要的代价a和将它与前面的地雷相连所需要的代价b * d(d 需要安置的地雷的数量,即当前的1与前一个1之间0的个数)的大小关系,即判断a与b * d谁小,谁小就把谁加在答案上,即可求出答案。(每次加过答案之后,记得将d清零哦)(需要特殊注意一下第一颗地雷,即第一个1,计数过程中不必记上第一个1前面的0,因为它们并没有被安装地雷的必要,对于这点我将一开始d的数量设置的较大,这样a便会小于b * d,再将d清零即可)。

/*题目样例*/
input
2
1 1
01000010
5 1
01101110
output
2
6
/*B*/
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int main(){
    int t,a,b;
    char s[N];
    scanf("%d",&t);
    for(int i=1;i<=t;i++){
        int ans=0,d=10000;
        cin>>a>>b>>s+1;
        for(int j=1;j<=strlen(s+1);j++){
            if(s[j]=='1') ans+=min(a,b*d),d=0;
            else d++;
        }
        cout<<ans<<endl;
    }
    return 0;
}

C题 题目链接

题目大意
小明在n个不同的餐馆均点了一道菜,共n道。对于第i个餐馆,小明可以选择请这家餐馆的外卖员送餐,外卖员会在第a[i]分钟送达,或者自己花费b[i]分钟去餐厅取餐到家。所有餐厅的外卖员可以并行工作,小明只能一次取一份餐。
求最短的时间使n道菜全部到达小明家。

输入
第一行为一个正整数t(1≤t≤2e5)——测试用例的数量。
每个测试用例以一行包含一个整数n (1≤n≤2e5)——小明点的菜的数量。
每一个测试用例的第二行包含n个整数a[1]…a[ n ] (1≤a[i]≤1e9)——第i家餐厅外卖员送餐花费的时间。
每个测试用例的第三行包含n个整数b[1]…b[n] (1≤b[i]≤1e9)——小明自己去第i家餐厅取餐回家花费的时间。
所有测试用例的n之和不超过2e5。

输出
对于每个测试用例,输出一个整数——所有菜都到达小明家的花费的最少时间。

解题思路
如果小明选择所有餐均由外卖员配送,那么所花费的时间便是a[i]max,在这种情况下如果小明自己选择几个配送时间较长的餐馆去取餐,那么所花费的时间可能会减少。所以易知,答案的范围必然包含在a[i]的范围里,即包含于1~1e9。知道了答案的范围我们便可以二分求解,找到花费时间的最小值。

/*题目样例*/
input
4
4
3 7 4 5
2 1 2 4
4
1 2 3 4
3 3 3 3
2
1 2
10 10
2
10 10
1 2
output
5
3
2
3
/*C*/
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int a[N],b[N],n;
bool cheak(int mid){
    long long int sum=0;
    for(int j=1;j<=n;j++)
        if(a[j]>mid) sum+=b[j];
    if(sum>mid) return false;
    else return true;
}

int main(){
    int t;
    scanf("%d",&t);
    for(int i=1;i<=t;i++){
        scanf("%d",&n);
        for(int j=1;j<=n;j++) scanf("%d",&a[j]);
        for(int j=1;j<=n;j++) scanf("%d",&b[j]);
        int l=1,r=1e9,ans=1e9;
        while(l<=r){
            int mid=(l+r)/2;
            if(cheak(mid)) r=mid-1,ans=mid;
            else l=mid+1;
        }
        printf("%d\n",ans);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值