cf平台刷题日常

706B - Interesting drink

直接使用vector来存放数据,再每个判断多少个数据少于num即可;

但是这里有个很大的陷阱,那就是时间限制,直接使用for循环给vec是错误的,必须使用二分法查找才能通过,这也给我提供了一个新的思路,如果使用循环超时的话,可以考虑一下二分法查找;

代码:

#include
#include
#include
#include
#include
#include
#include

using namespace std;

#define LL long long;

int n,q,a,ci;
long long  num;
vector vec;

int main(){
	cin>>n;
	for(int i=0;i>a;
		vec.push_back(a);
	}
	sort(vec.begin(),vec.end());
	cin>>q;
	for(int i=0;i>num;
		int l=0,r=n-1;
		while(l<=r) {
			int mid=(l+r)/2;
			if(num>=vec[mid]) {
				l=mid+1;
			} else {
				r=mid-1;
			}
		}
		cout<

919.Perfect Number:

这题就是判断位数加法有没有等于10,思路是把i每隔9判断一次,但是当i=190以后,就不一定全部都符合了,这是就要isPerfect函数加以判断才行

代码:

#include
#include
#include
#include
#include
#include
#include
#include

using namespace std;

#define LL long long;

int maxn=1111111111;
int n;

bool isPerfect(int i) {
	int res=0;
	while(i) {
		res+=(i%10);
		i/=10;
	}
	if(res==10) {
		return true;
	} else {
		return false;
	}
}

int main() {
	cin>>n;
	for(long long i=19;i<=maxn;i+=9) {
		if(isPerfect(i)) {
			n--;
		} 
		if(n==0) {
			cout<

1099B. Squares and Segments

思路:首先要理解题目的意思,题目要求输入一个数n,将这个数分解为x,x的乘积,输出x+x的和,当n平方根不是整数时,就求它的x,x+1或者x+1,x+1的乘积,比较最接近的那个进行求和。

代码:

#include
#include
#include
#include
#include
#include
#include
#include

using namespace std;

#define LL long long;

const int inf=0x3f3f3f3f; 

int n;
int res=inf;

int main() {
	cin>>n;
	if(n==1) {
		res=2;
		cout<=n) {
		res=2*p+1;
	} else {
		res=2*(p+1);
	}
	cout<

解析:”最接近“其实并不需要完成的按照字面意思来进行逻辑处理,这个数在平方根求解后只能在[x^2,(x+1)^2)上,所以在当n<=x*(x+1)时就输出2*x+1即可。

195A.Let's watch Football:

我的思路:主要是看懂题目,题目是求你在等待多少秒后,可以完成边看边下且不会暂停的最小等待时间;

解析:首先要找到这题的规律,先看在边播边放的情况下,视频可以下载多大,在用剩下的时间就是等待时间的总下载大小;

代码:

#include
#include
#include
#include
#include
#include
#include
#include

using namespace std;

#define LL long long;

const int inf=0x3f3f3f3f; 

int a,b,c;

int main() {
	cin>>a>>b>>c;
	int total=a*c,con=b*c;
	int wait=(total-con)/b;
	if((total-con)%b!=0) {
		wait++;
	}
	cout<

743B - Chloe and the sequence

我的思路:一开始想到的方法是使用string来存储数据,然后用str[k-1]输出,但是如何把string,int和string连接一起呢?然后我又想到了使用vector来存储,但是如果使用vector来存储全部之前的步数,只能一个个添加在后面肯定会超时,但是使用vector>存储的话,在存进结果ivec时,又只能存vector。。。

代码:

#include
#include
#include
#include
#include
#include
#include
#include

using namespace std;

#define LL long long;

const int inf=0x3f3f3f3f; 
int n,k,m;
vector vec;
vector< vector > ivec,tmp;

int main() {
	cin>>n>>k;
	m=0;
	for(int i=0;i1) {
			ivec.push_back(tmp);       //问题就是出在这里,无法存储vector< vector >
		}
		tmp=ivec;
		vec.clear();
	}
	int sz=ivec.size()-1;
	cout<

思路2:这题我在网上找了很多的答案,大概有两个思路,两个思路都不是很懂,一个是使用递归的思路,另一个是使用GCC处理二进制位的内置函数,详细的解释在补充。

使用递归的代码:

#include
#include
#include
#include
#include
#include
#include
#include

#define LL long long
using namespace std;

const int inf=0x3f3f3f3f; 
 
LL dfs(LL k, LL n){
    if(n == 1)  return n;
    LL t = (1LL<<(n-1));
    if(k == t)  return n;
    if(k > t)  return dfs(k-t, n-1);
    return dfs(k, n-1);
}
 
int main(){
    LL k, n;
    while(cin >> n >> k){
        cout<

使用GCC内置函数代码:

#include 
#include 
#include 
#include 
#include 
using namespace std;
int main()
{
	long long  k,n;
	cin>>n>>k;
	cout<<__builtin_ffsll(k);
}

--------------------- 
作者:切克脑 
来源:CSDN 
原文:https://blog.csdn.net/qq_28606665/article/details/76147161 

166A.Rank List

我的思路:使用map函数存储数据,然后按照p-th来排列,再使用一个数组存储相同队伍的数量,数据的位置对应第几名,但是当我仔细学习了map函数后发现,它虽然会自动排列索引值,但也会自动排除相同的键值对。

网上思路:使用结构体来保存problems和penaltytime,然后找到目标后向两边扩展,找到和目标相同的个数。

网上的代码:

#include
#include
#include
#include
#include
#include
#include
#include

#define LL long long
using namespace std;

const int inf=0x3f3f3f3f; 

struct team
{
	int problems;
	int penaltytime;
};

bool cmp(team t1,team t2) {
	return t1.problems>t2.problems 
	|| (t1.problems==t2.problems && t1.penaltytime>n>>k;
    for(int i=0;i>t[i].problems>>t[i].penaltytime;
    }
    sort(t,t+n,cmp);
    k-=1;
    int l(k),r(k);
    while(l>0 && t[l-1].problems==t[k].problems &&t[l-1].penaltytime==t[k].penaltytime) {
    	l-=1;
    }
    while(r+1

解析代码:对结构体team中的元素使用时,不能使用->而要使用.来连接,3个参数的sort,第三个参数是sort以什么方式来排序,int l(k)其实就是int l=k;两个while循环是以目标t[k]为中心,分别向两边散开,最后输出相同的次数。

1042A.Benches

我的思路:要求最小的最大容量,首先我们必须先对数组进行排序,我们再把m分别加入数据中,直到所有的值都等于原数组中的最大值,如果没有所有大最大值就已经结束,那么就输出数组的最大值,如果全部都等于最大值还未结束,那就把m平分到n个数据中,如果有余,就再加一。那要求最大的最大容量就比较简单了,直接把m加上数组的最大值即可。

代码:

#include
#include
#include
#include
#include
#include
#include
#include

#define LL long long
using namespace std;

const int inf=0x3f3f3f3f; 
const int maxn=10010;

int a[maxn];
int n,m,mink,maxk;

int maxa(int a[]) {

}

int main(){
	cin>>n>>m;
	for(int i=0;i>a[i];
	}
	sort(a,a+n);
	maxk=a[n-1]+m;
	for(int i=0;i

911B.Two cakes

这题我目前还不是很懂,只是在网上找到了答案,但是没有看懂题目的意思,暂时先放着。

网上代码:

#include
#include
#include
#include
#include
#include
#include
#include

#define LL long long
using namespace std;

int a,b,n;

int main(){
	cin>>n>>a>>b;
	int res=0;
	for(int i=1;i

1011B.Planning The Expedition

完全不明白题目的意思,看了代码也不懂。。。

网上代码:

#include
#include
#include
 
using namespace std;
 
int foods[101];
 
int find_res(int people, int l, int r)
{
	int p = 0;
	if (r - l == 1)
	{
		for (int i = 0; i <= 100; i++)
			p += foods[i] / r;
		if (p >= people)
			return r;
		else
			return l;
	}
	int m = (l + r) >> 1;
	for (int i = 0; i <= 100; i++)
		p += foods[i] / m;
	if (p >= people)
		return find_res(people, m, r);
	else
		return find_res(people, l, m);
}
 
int main()
{
	int n, m;
	while (cin >> n >> m)
	{
		int type;
		memset(foods, 0, sizeof(foods));
		for (int i = 0; i < m; i++)
		{
			cin >> type;
			foods[type]++;
		}
		cout << find_res(n, 0, 100) << endl;
	}
	return 0;
}

489C.Given Length and Sum of Digits

思路:这题使用的是贪心算法,一共有以下几种情况:

  1. 输出0 0,就是m=1,s=0时,就只有0,0一种结果
  2. 输出-1 -1,就是错误的情况,分别是s=0,但m!=0和m*9
  3. 当s<=9时,很明显就只有一个数字
    1. s=1时,就是最大最小值一样
    2. s!=1时,最小值是个位数为s-1,最高位为1,其余是0,即是最小(因为我代码使用的是全局变量,系统已经自动初始化为0),最大值就是最高位为s
  4. s>9时,这样就得分别求最大最小值了
    1. 最小值,从个位数开始,9开始添加,当添加到s<=9时停止
      1. 当m=1时,就把最末位为s即可
      2. 其余时,我们按照s<=9情况来求最小值
    2. 最大值,从最高位开始,9开始添加,当添加到s<=9时停止
      1. 当m=0时,直接输出即可
      2. 当m!=0时,我们就把最后一个9的位数加一,这个位置的数就是s

代码:

#include
#include
#include
#include
#include
#include
#include
#include

#define LL long long
using namespace std;

int a[101],b[101],i,j,tmp1,tmp2;    //i为最小值最后添加9的位置,j为最大值添加9的位置,tmp1,tmp2分别为求最大值时m和s的值,a[],b[]分别为最小值和最大值
int m,s;

int main(){
	cin>>m>>s;
	tmp1=m,tmp2=s;
	if(m==1&&s==0) {
		cout<<0<<" "<<0<=0;k--) {
				cout<9) {
		if(m==1) {
			cout<<-1<<" "<<-1<0&&s>9) {
			a[i]=9;
			s-=9;
			m--;
			i++;
		}
		int u=i+m-1;
		if(m==1) {
			a[u]=s;
		} else {
			a[i]=s-1;
			a[u]=1;
		}
		while(tmp1>0&&tmp2>9) {
			b[j]=9;
			tmp2-=9;
			tmp1--;
			j++;
		}
		if(tmp1!=0) {
			b[j]=s;
		}
		for(int k=u;k>=0;k--) {
			cout<

总结:这题说是贪心算法,其实就是分清楚有什么情况,每种情况需要做什么,这个看起来很简单,其实一点也不简单,我总结了以下我在写代码的时候遇到以下几种错误的情况:

  1. 在m!=1,s=1时,我没有想到最大最小值是一样的,我以为最小值是1
  2. 在输出最大值时,我并没有考虑到以后0位数的输出
  3. 我没有注意到一个细节,在s>9的情况中,while循环中是先添加再i++的,这样的话while循环一出,i已经是最后添加9的下一位了

489B - BerSU Ball

这题的意思我没有看懂,题目我并没有看懂配对的条件,在网上找了一下思路,结果是两数之差的绝对值不大于1即可配对???在题目中我真的没看出来,姑且接受他的要求吧

代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include

#define LL long long
using namespace std;

const LL maxn=110;

int a[maxn],b[maxn];
int res,n,m;

int main(){
	cin>>n;
	for(int i=0;i>a[i];
	}
	cin>>m;
	for(int i=0;i>b[i];
	}
	sort(a,a+n);
	sort(b,b+m);
	for(int i=0,j=0;ib[j]) {
			j++;
		}
	}
	cout<

解析:只要知道思路和对数组进行排序后就十分简单了

327A - Flipping Game

我的思路:统计0和1的数量,记录最大的0的连续数量,加上1的数量。但是问题在于如果0中夹杂这1,而且1的数量比0小时,还是得计算上差的值,这个逻辑就很难实现

网上的思路:我们可以用两个数组,一个来存储数据,一个来存储差,0表示为1,1表示为-1。用maxl来计算一次操作的最大0,1之间的数量差,再记录上1的数量,相加就是答案

代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LL long long

using namespace std;

const LL maxn=110;

int a[maxn],num[maxn];
int sum,count1,n;

int main(){
	cin>>n;
	for(int i=0;i>a[i];
	}
	for(int i=0;imaxl) {
			maxl=sum;
		} 
		if(sum<0) {
			sum=0;
		}
	}
	cout<

解析:这题问题在于有没有想到使用另一个数组来计算数量差关系,想到就可以AC了。

270A.Fancy Fence

这题比较有意思,看题目像是一道很简单的题,直接暴力即可,但是其实有陷阱在里面

我的思路:直接用for循环暴力判断,但是不是每个角都能整除,所以会存在偏差,所以暴力法无法解决这个问题

网上思路:如果暴力法不行,而且还不知道角度x要构成多边形的条件,这题就永远做不出来,那么x要满足什么条件才能构成多边形呢,有个数学公式:360%(180-x)==0,x为每个角度度数。了解到这个就是道简单题了

代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LL long long

using namespace std;

const LL maxn=185;

int a[maxn];
int t;

int main(){
	cin>>t;
	for(int i=0;i>a[i];
		if(360%(180-a[i])==0) {
			cout<<"YES"<

解析:虽然说这个代码上交是正确的,但是在我的编译器验证119的时候还是显示"NO"的,但是提交上去就是"YES",不知道为什么。

556A.Case of the Zeros and Ones

这题一看以为和字符串的操作有关,其实就是一道简单的数学题。

代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LL long long

using namespace std;

const LL maxn=200009;

char a[maxn];
int n,num0,num1,ci;

int main() {
	cin>>n;
	for(int i=0;i>a[i];
		if(a[i]=='0') {
			num0++;
		} else if(a[i]=='1') {
			num1++;
		}
	}
	ci=min(num0,num1);
	cout<

解析:统计出0和1的数量,选出较小者进行删减即可;

476A.Dreamoon and Stairs

这题暴力法解决,求出每步都走2时的步数,如果最后一步不足2,就走1步,然后判断这时的步数能不能被m整除,不行就把2变成1+1,如果全部都变成1还是不能满足就输出-1;

代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LL long long

using namespace std;

const LL maxn=200009;

int n,m,ci,yu;

int main() {
	cin>>n>>m;
	if(n

478A. Initial Bet

这题只要找到规律就是一道水题,求出平均值,再每个数减去平均值,只要差等于0,这个差就是初始值。

代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LL long long

using namespace std;

const LL maxn=200009;

int res,cha;
int c[6];

int main() {
	for(int i=0;i<5;i++) {
		cin>>c[i];
		res+=c[i];
	}
	if(res%5!=0 || res==0) {
		cout<<-1<

520B - Two Buttons

我的思路:这题一拿到就是使用分情况处理的方法来解决,从n到m,判断n*2和m之间的大小关系,再分情况进行判断,这种方法求出来的次数并不一定是最小的次数。

网上的思路:我们不用n到m的转化,可以从m到n的转化,这样转化就简单很多,直接判断m是否为偶数,是则减半,不是则加一来使它成为偶数。

网上代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LL long long

using namespace std;

const LL maxn=200009;

int n,m;
int res;

int main() {
	cin>>n>>m;
	while(n

474B - Worms

这题逻辑十分简单,直接判断数在哪个区间内,但是问题是时间复杂度的问题。

我的代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LL long long

using namespace std;

const LL maxn=100009;

int n,m;
int a[maxn],q[maxn];

int main() {
	cin>>n;
	for(int i=0;i>a[i];
	}
	cin>>m;
	for(int i=0;i>q[i];
	}
	for(int i=0;i(j+a[k])) {
			j+=a[k];
			k++;
		}
		cout<

解析:这个代码是会超时的,因为每次来一个数就要从第一个区间开始判断,所以我的更改代码是给q数组排序,但是这样输出的顺序就不同,也不行

网上的思路:使用另一个数组来存放区间数,在输入的时候直接判断在哪个区间;

网上代码:

#include
#include
#include
#include
using namespace std;
int com[1000008];
int main()
{
    int n;
    while(cin>>n)
    {
        int a[100008];
        for(int i=0; i>a[i];
        for(int i=1; i>m;
        while(m--)
        {
            int temp;
            cin>>temp;
            cout<

我按网上代码写的代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LL long long

using namespace std;

const int maxn=100008;

int q[maxn];
int n,m,num;

int main() {
	while(cin>>n) {
		int a[maxn];
		for(int i=0;i>a[i];
		}
		for(int i=1;i>m;
		while(m--)
        {
            int temp;
            cin>>temp;
            cout<

这两个一样的代码,为什么我的就是不行呢??

37A - Towers

这题很简单,就是一开始理解不了题意,题意是找出数组最大的重复数和一共存在多少个不同的数;

// sub.cpp: 定义控制台应用程序的入口点。
//
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#define LL long long

using namespace std;

LL GCD(LL a, LL b) {
	if (a ivec, int l, int r, int res) {
	while (l <= r) {
		int mid = (l + r) / 2;
		if (ivec[mid] <= res) {
			l = mid + 1;
		}
		else {
			r = mid - 1;
		}
	}
	return l;	//二分法查询,res为目标值
}

string BinaryCout(int x) {
	int a;
	string res;
	while (x != 0) {
		a = x % 2;
		x >>= 1;
		//res += to_string(a);
	}
	return res;		//转化成二进制的字符串类型
}

bool isPrime(int x) {
	for (int i = 2;i> n;
	for (int i = 0; i < n; i++)
	{
		cin >> a[i];
	}
	sort(a, a + n);
	for (int j = 0; j < n ; j++)
	{
		b[a[j]]++;
	}
	sort(b, b + 10000);
	for (int k = 0; k < maxn; k++)
	{
		if (b[k]) {
			c++;
		}
	}
	cout << b[9999] << " " << c;
	return 0;
}

 

 

待续   -5.5 22:48

你可能感兴趣的:(codeforce,练习题记录)