Round #653 (Div. 3)前两题&Round #650 (Div. 3)第三题

呜呜呜呜我因为太菜被关起来了。
昨天一道超时,两道超时,只会暴力的我只好去睡觉了。
今天补题。
嗯,从第一题开始。

A. Required Remainder

You are given three integers x,y and n. Your task is to find the maximum integer k such that 0≤k≤n that kmodx=y, where mod is modulo operation. Many programming languages use percent operator % to implement it.
In other words, with given x,y and n you need to find the maximum possible integer from 0 to n that has the remainder y modulo x.
You have to answer t independent test cases. It is guaranteed that such k exists for each test case.
Input
The first line of the input contains one integer t (1≤t≤5⋅104) — the number of test cases. The next t lines contain test cases.
The only line of the test case contains three integers x,y and n (2≤x≤109; 0≤y<x; y≤n≤109).
It can be shown that such k always exists under the given constraints.
Output
For each test case, print the answer — maximum non-negative integer k such that 0≤k≤n and kmodx=y. It is guaranteed that the answer always exists.

不要害怕,题目很长,但还是能懂,就是从[0,k]中找到最大的k,让k%x==y,如果枚举肯定超时,聪明一点,就二分,再聪明一点,emmm来看看大佬的代码。。。

#include<bits/stdc++.h>
using namespace std;
int main(){
	int t,x,y,n;
	cin>>t;
	while(t--){
		cin>>x>>y>>n;
		cout<<(n-y)/x*x+y<<endl;
	}
	return 0;
}

在这里插入图片描述
就不多说了。。

B. Multiply by 2, divide by 6

You are given an integer n. In one move, you can either multiply n by two or divide n by 6 (if it is divisible by 6 without the remainder).
Your task is to find the minimum number of moves needed to obtain 1 from n or determine if it’s impossible to do that.
You have to answer t independent test cases.
Input
The first line of the input contains one integer t (1≤t≤2⋅104) — the number of test cases. Then t test cases follow.
The only line of the test case contains one integer n (1≤n≤109).
Output
For each test case, print the answer — the minimum number of moves needed to obtain 1 from n if it’s possible to do that or -1 if it’s impossible to obtain 1 from n.

不要被吓哭了哦,题意大概是从给定的数出发,✖2或者➗6,不停地重复以上步骤,用最少的次数得到1,如果无法得到输出-1。
因为大佬的代码有点深奥,我又去复习了一遍循环。。我只是确认一下(www太菜辣)

for ( init; condition; increment )
{
   statement(s);
}

①init 会首先被执行,且只会执行一次。这一步允许您声明并初始化任何循环控制变量。您也可以不在这里写任何语句,只要有一个分号出现即可。
②接下来,会判断 condition。如果为真,则执行循环主体。如果为假,则不执行循环主体,且控制流会跳转到紧接着 for 循环的下一条语句。
③在执行完 for 循环主体后,控制流会跳回上面的 increment 语句。该语句允许您更新循环控制变量。该语句可以留空,只要在条件后有一个分号出现即可。
④条件再次被判断。如果为真,则执行循环,这个过程会不断重复(循环主体,然后增加步值,再然后重新判断条件)。在条件变为假时,for 循环终止。
在这里插入图片描述

上来要判断condition,否则一次都不执行。

聚聚的思想就是用2和3来削这个数,如果削不到1就没有可能通过✖2或者➗6的操作送到1,为什么呢?老费说过,乘就是除,除就是乘,要想到1必须通过➗6的操作,而在✖2之后想具备被6除到1的条件,其自身必须要是3的倍数,因为要统计乘2的次数,所以在这里也有对它是2的多少倍做个计数。
聚聚是先用2削,再用3削;我这里换一下看看可不可行,先用3削(num1次),再用2削(num2次)。如果削不到1不行,或者num2>num1也不行(用的2多3少,如果拿3的数目凑6,说明除完6还要除2,但是我们没有除2的操作可选;如果拿2的数目凑6,说明不够除还要乘3,但是我们也没有乘3的操作可选);else如果削到了1,且num2<=num1(用的3多2少,如果拿2的数目凑6,说明除完6还要除3,但是我们没有除3的操作可选;如果拿3的数目凑6,说明不够除还要乘2,我们正好可以选择乘2!)
所以这里我们的操作数就是多的那个(也就是num1)作为除6的次数,然后补上(num1-num2)也就是差的2的个数,作为乘2的次数。
呼——终于讲清楚了!OKK,上吧,代码!

#include<bits/stdc++.h>
int main(){
	std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int t;std::cin>>t;
    while(t--){
    	int n;std::cin>>n;
    	int num1=0;int num2=0;
    	for(;n%3==0;n/=3) num1++;
    	for(;n%2==0;n/=2) num2++;
    	if(n>1||num1<num2) std::cout<<"-1\n";//注意,加速了换行就不能用endl了
    	else std::cout<<num1*2-num2<<"\n";//注意,加速了换行就不能用endl了
    }
    return 0;
}

然后趁机混入第一场没做出来的650轮的第三题hhhh。

C. Social Distance

Polycarp and his friends want to visit a new restaurant. The restaurant has n tables arranged along a straight line. People are already sitting at some tables. The tables are numbered from 1 to n in the order from left to right. The state of the restaurant is described by a string of length n which contains characters “1” (the table is occupied) and “0” (the table is empty).
Restaurant rules prohibit people to sit at a distance of k or less from each other. That is, if a person sits at the table number i, then all tables with numbers from i−k to i+k (except for the i-th) should be free. In other words, the absolute difference of the numbers of any two occupied tables must be strictly greater than k.
For example, if n=8 and k=2, then:
strings “10010001”, “10000010”, “00000000”, “00100000” satisfy the rules of the restaurant;
strings “10100100”, “10011001”, “11111111” do not satisfy to the rules of the restaurant, since each of them has a pair of “1” with a distance less than or equal to k=2.
In particular, if the state of the restaurant is described by a string without “1” or a string with one “1”, then the requirement of the restaurant is satisfied.
You are given a binary string s that describes the current state of the restaurant. It is guaranteed that the rules of the restaurant are satisfied for the string s.
Find the maximum number of free tables that you can occupy so as not to violate the rules of the restaurant. Formally, what is the maximum number of “0” that can be replaced by “1” such that the requirement will still be satisfied?
For example, if n=6, k=1, s= “100010”, then the answer to the problem will be 1, since only the table at position 3 can be occupied such that the rules are still satisfied.
Input
The first line contains a single integer t (1≤t≤104) — the number of test cases in the test. Then t test cases follow.
Each test case starts with a line containing two integers n and k (1≤k≤n≤2⋅105) — the number of tables in the restaurant and the minimum allowed distance between two people.
The second line of each test case contains a binary string s of length n consisting of “0” and “1” — a description of the free and occupied tables in the restaurant. The given string satisfy to the rules of the restaurant — the difference between indices of any two “1” is more than k.
The sum of n for all test cases in one test does not exceed 2⋅105.
Output
For each test case output one integer — the number of tables that you can occupy so as not to violate the rules of the restaurant. If additional tables cannot be taken, then, obviously, you need to output 0.

小天使 小蒟蒻又来讲解题目大意啦~不知为何这么长也不难懂哈 ~ 🐕手动狗头保命
首先给的是样例个数,然后每个样例的第一行是桌子数和人与人之间的最小distance(也就是如果某个位置是1,也就是做了人的话,方圆distance里不能有人),样例第二行给的是桌子的坐人情况。
输出就是这列桌子还能坐多少人。
说实话这题有点傻眼,让我们来想一想 看看大佬的码hhhh

  1. 首先看看全0,也就是桌子全空,怎么坐人:以可以坐人的位置为界,将桌子们划分开来,由于是从前往后划区,所以最后一个区也要补齐,就将n+k,然后除以k吗?不对,人坐的那个位置也要算,也就是说每个区是(k+1)的长度。所以,全零的情况可以坐的人数为:(n+k)/(k+1)
  2. 如果不是全零,那就是初始已有人坐了,那么我们将可以坐人的零列分块,分成第一个块(第一个人前面的0列),中间部分和最后一个块(最后一个人后面的0列)三部分。当然了,也不排除没有第一部分和最后一部分(首尾都有人的情况)。①第一部分:我们首先记录下1的下标(从0开始的),那么第一个1的下标就是他前面的0的个数/(k+1)就是可以坐的人数 ②第二部分:后面的1的下标减去前面的1的下标再减1,就是当中0的个数 减去k 再除以(k+1)就是中间可以坐下的人数(因为是从前一个人人开始划分领地,所以要把属于下一个人的领地减掉) ③第三部分:(总的桌子数-最后一个人的下标-1)就是最后一串0的长度,由于后面已经没有人了,所以除以(k+1)就好了
#include <bits/stdc++.h>
int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int cases;std::cin>>cases;
    while(cases--){
    	int n,k,res=0;std::string str;//注意这里string前面也要std::
    	std::cin>>n>>k;
    	std::cin>>str;
    	std::vector<int> v;
    	for(int i=0;i<n;i++)
    		if(str[i]=='1') v.push_back(i);//vector是push_back
    	if(v.empty()) std::cout<<(n+k)/(k+1)<<"\n";
    	else{
    		res+=v[0]/(k+1);
    		for(int i=0;i<int(v.size())-1;i++){
    			res+=(v[i+1]-v[i]-1-k)/(k+1);
    		}
    		res+=(n-v.back()-1)/(k+1);
    		std::cout<<res<<"\n";
    	}
    }
    return 0;
}
summery:

多打草稿,多动脑子,放一张戈薇大姐头的图,这种又会跑又会动脑子的女主,你舅宠她爸!
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值