706B - Interesting drink
直接使用vector<int>来存放数据,再每个判断多少个数据少于num即可;
但是这里有个很大的陷阱,那就是时间限制,直接使用for循环给vec是错误的,必须使用二分法查找才能通过,这也给我提供了一个新的思路,如果使用循环超时的话,可以考虑一下二分法查找;
代码:
#include<iostream>
#include<string.h>
#include<cstdio>
#include<set>
#include<memory.h>
#include<algorithm>
#include<vector>
using namespace std;
#define LL long long;
int n,q,a,ci;
long long num;
vector<int> vec;
int main(){
cin>>n;
for(int i=0;i<n;i++) {
cin>>a;
vec.push_back(a);
}
sort(vec.begin(),vec.end());
cin>>q;
for(int i=0;i<q;i++) {
cin>>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<<l<<endl;
}
return 0;
}
919.Perfect Number:
这题就是判断位数加法有没有等于10,思路是把i每隔9判断一次,但是当i=190以后,就不一定全部都符合了,这是就要isPerfect函数加以判断才行
代码:
#include<iostream>
#include<string.h>
#include<cstdio>
#include<set>
#include<memory.h>
#include<algorithm>
#include<vector>
#include<math.h>
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<<i<<endl;
break;
}
}
return 0;
}
1099B. Squares and Segments
思路:首先要理解题目的意思,题目要求输入一个数n,将这个数分解为x,x的乘积,输出x+x的和,当n平方根不是整数时,就求它的x,x+1或者x+1,x+1的乘积,比较最接近的那个进行求和。
代码:
#include<iostream>
#include<string.h>
#include<cstdio>
#include<set>
#include<memory.h>
#include<algorithm>
#include<vector>
#include<math.h>
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<<res<<endl;
return 0;
}
int p=sqrt(n);
if(p*p==n) {
res=2*p;
} else if(p*(p+1)>=n) {
res=2*p+1;
} else {
res=2*(p+1);
}
cout<<res<<endl;
return 0;
}
解析:”最接近“其实并不需要完成的按照字面意思来进行逻辑处理,这个数在平方根求解后只能在[x^2,(x+1)^2)上,所以在当n<=x*(x+1)时就输出2*x+1即可。
195A.Let's watch Football:
我的思路:主要是看懂题目,题目是求你在等待多少秒后,可以完成边看边下且不会暂停的最小等待时间;
解析:首先要找到这题的规律,先看在边播边放的情况下,视频可以下载多大,在用剩下的时间就是等待时间的总下载大小;
代码:
#include<iostream>
#include<string.h>
#include<cstdio>
#include<set>
#include<memory.h>
#include<algorithm>
#include<vector>
#include<math.h>
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<<wait<<endl;
return 0;
}
743B - Chloe and the sequence
我的思路:一开始想到的方法是使用string来存储数据,然后用str[k-1]输出,但是如何把string,int和string连接一起呢?然后我又想到了使用vector来存储,但是如果使用vector<int>来存储全部之前的步数,只能一个个添加在后面肯定会超时,但是使用vector<vector<int>>存储的话,在存进结果ivec时,又只能存vector<int>。。。
代码:
#include<iostream>
#include<string.h>
#include<cstdio>
#include<set>
#include<memory.h>
#include<algorithm>
#include<vector>
#include<math.h>
using namespace std;
#define LL long long;
const int inf=0x3f3f3f3f;
int n,k,m;
vector<int> vec;
vector< vector<int> > ivec,tmp;
int main() {
cin>>n>>k;
m=0;
for(int i=0;i<n;i++) {
m++;
vec.push_back(m);
ivec.push_back(vec);
if(m>1) {
ivec.push_back(tmp); //问题就是出在这里,无法存储vector< vector<int> >
}
tmp=ivec;
vec.clear();
}
int sz=ivec.size()-1;
cout<<ivec[sz][k-1]<<endl;
return 0;
}
思路2:这题我在网上找了很多的答案,大概有两个思路,两个思路都不是很懂,一个是使用递归的思路,另一个是使用GCC处理二进制位的内置函数,详细的解释在补充。
使用递归的代码:
#include<iostream>
#include<string.h>
#include<cstdio>
#include<set>
#include<memory.h>
#include<algorithm>
#include<vector>
#include<math.h>
#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<<dfs(k,n)<<endl;
}
return 0;
}
//网上的代码,使用递归的函数求解,不懂其中的逻辑关系;
使用GCC内置函数代码:
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <queue>
#include <string.h>
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<iostream>
#include<string.h>
#include<cstdio>
#include<set>
#include<memory.h>
#include<algorithm>
#include<vector>
#include<math.h>
#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<t2.penaltytime);
}
int main(){
int n,k;
team t[80];
cin>>n>>k;
for(int i=0;i<n;i++) {
cin>>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<n && t[r+1].problems==t[k].problems &&t[r+1].penaltytime==t[k].penaltytime) {
r++;
}
cout<<r-l+1<<endl;
return 0;
}
解析代码:对结构体team中的元素使用时,不能使用->而要使用.来连接,3个参数的sort,第三个参数是sort以什么方式来排序,int l(k)其实就是int l=k;两个while循环是以目标t[k]为中心,分别向两边散开,最后输出相同的次数。
1042A.Benches
我的思路:要求最小的最大容量,首先我们必须先对数组进行排序,我们再把m分别加入数据中,直到所有的值都等于原数组中的最大值,如果没有所有大最大值就已经结束,那么就输出数组的最大值,如果全部都等于最大值还未结束,那就把m平分到n个数据中,如果有余,就再加一。那要求最大的最大容量就比较简单了,直接把m加上数组的最大值即可。
代码:
#include<iostream>
#include<string.h>
#include<cstdio>
#include<set>
#include<memory.h>
#include<algorithm>
#include<vector>
#include<math.h>
#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<n;i++) {
cin>>a[i];
}
sort(a,a+n);
maxk=a[n-1]+m;
for(int i=0;i<n-1;i++) {
while(a[i]!=a[n-1]) {
a[i]++;
m--;
if(m==0) {
mink=a[n-1];
break;
}
}
if(m==0) {
break;
}
}
if(m!=0) {
int add=m/n;
if(m%n==0) {
mink=a[0]+add;
} else {
mink=a[0]+add+1;
}
}
cout<<mink<<" "<<maxk<<endl;
return 0;
}
911B.Two cakes
这题我目前还不是很懂,只是在网上找到了答案,但是没有看懂题目的意思,暂时先放着。
网上代码:
#include<iostream>
#include<string.h>
#include<cstdio>
#include<set>
#include<memory.h>
#include<algorithm>
#include<vector>
#include<math.h>
#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<n;i++) {
res=max(min(a/i,b/(n-i)),res);
}
cout<<res<<endl;
return 0;
}
1011B.Planning The Expedition
完全不明白题目的意思,看了代码也不懂。。。
网上代码:
#include<iostream>
#include<cstring>
#include<algorithm>
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
思路:这题使用的是贪心算法,一共有以下几种情况:
- 输出0 0,就是m=1,s=0时,就只有0,0一种结果
- 输出-1 -1,就是错误的情况,分别是s=0,但m!=0和m*9<s的两种情况
- 当s<=9时,很明显就只有一个数字
- s=1时,就是最大最小值一样
- s!=1时,最小值是个位数为s-1,最高位为1,其余是0,即是最小(因为我代码使用的是全局变量,系统已经自动初始化为0),最大值就是最高位为s
- s>9时,这样就得分别求最大最小值了
- 最小值,从个位数开始,9开始添加,当添加到s<=9时停止
- 当m=1时,就把最末位为s即可
- 其余时,我们按照s<=9情况来求最小值
- 最大值,从最高位开始,9开始添加,当添加到s<=9时停止
- 当m=0时,直接输出即可
- 当m!=0时,我们就把最后一个9的位数加一,这个位置的数就是s
- 最小值,从个位数开始,9开始添加,当添加到s<=9时停止
代码:
#include<iostream>
#include<string.h>
#include<cstdio>
#include<set>
#include<memory.h>
#include<algorithm>
#include<vector>
#include<math.h>
#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<<endl;
} else if(s==0 || m*9<s) {
cout<<-1<<" "<<-1<<endl;
} else if(s<=9) {
if(m==1) {
cout<<s<<" "<<s<<endl;
} else {
a[0]=s-1;
a[m-1]=1;
b[0]=s;
for(int k=m-1;k>=0;k--) {
cout<<a[k];
}
cout<<" ";
for(int k=0;k<m;k++) {
cout<<b[k];
}
}
} else if(s>9) {
if(m==1) {
cout<<-1<<" "<<-1<<endl;
}
while(m>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<<a[k];
}
cout<<" ";
for(int k=0;k<j+tmp1;k++) {
cout<<b[k];
}
}
return 0;
}
总结:这题说是贪心算法,其实就是分清楚有什么情况,每种情况需要做什么,这个看起来很简单,其实一点也不简单,我总结了以下我在写代码的时候遇到以下几种错误的情况:
- 在m!=1,s=1时,我没有想到最大最小值是一样的,我以为最小值是1
- 在输出最大值时,我并没有考虑到以后0位数的输出
- 我没有注意到一个细节,在s>9的情况中,while循环中是先添加再i++的,这样的话while循环一出,i已经是最后添加9的下一位了
489B - BerSU Ball
这题的意思我没有看懂,题目我并没有看懂配对的条件,在网上找了一下思路,结果是两数之差的绝对值不大于1即可配对???在题目中我真的没看出来,姑且接受他的要求吧
代码:
#include<iostream>
#include<string.h>
#include<cstdio>
#include<set>
#include<memory.h>
#include<algorithm>
#include<vector>
#include<math.h>
#include<queue>
#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<n;i++) {
cin>>a[i];
}
cin>>m;
for(int i=0;i<m;i++) {
cin>>b[i];
}
sort(a,a+n);
sort(b,b+m);
for(int i=0,j=0;i<n&&j<m;) {
if(abs(a[i]-b[j])<=1) {
res++;
i++;
j++;
} else if(a[i]<b[j]) {
i++;
} else if(a[i]>b[j]) {
j++;
}
}
cout<<res<<endl;
return 0;
}
解析:只要知道思路和对数组进行排序后就十分简单了
327A - Flipping Game
我的思路:统计0和1的数量,记录最大的0的连续数量,加上1的数量。但是问题在于如果0中夹杂这1,而且1的数量比0小时,还是得计算上差的值,这个逻辑就很难实现
网上的思路:我们可以用两个数组,一个来存储数据,一个来存储差,0表示为1,1表示为-1。用maxl来计算一次操作的最大0,1之间的数量差,再记录上1的数量,相加就是答案
代码:
#include<iostream>
#include<string.h>
#include<cstdio>
#include<set>
#include<memory.h>
#include<algorithm>
#include<vector>
#include<math.h>
#include<queue>
#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<n;i++) {
cin>>a[i];
}
for(int i=0;i<n;i++) {
if(a[i]==1) {
num[i]=-1;
++count1;
} else {
num[i]=1;
}
}
int maxl=-2;
for(int i=0;i<n;i++) {
sum+=num[i];
if(sum>maxl) {
maxl=sum;
}
if(sum<0) {
sum=0;
}
}
cout<<maxl+count1<<endl;
return 0;
}
解析:这题问题在于有没有想到使用另一个数组来计算数量差关系,想到就可以AC了。
270A.Fancy Fence
这题比较有意思,看题目像是一道很简单的题,直接暴力即可,但是其实有陷阱在里面
我的思路:直接用for循环暴力判断,但是不是每个角都能整除,所以会存在偏差,所以暴力法无法解决这个问题
网上思路:如果暴力法不行,而且还不知道角度x要构成多边形的条件,这题就永远做不出来,那么x要满足什么条件才能构成多边形呢,有个数学公式:360%(180-x)==0,x为每个角度度数。了解到这个就是道简单题了
代码:
#include<iostream>
#include<string.h>
#include<cstdio>
#include<set>
#include<memory.h>
#include<algorithm>
#include<vector>
#include<math.h>
#include<queue>
#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<t;i++) {
cin>>a[i];
if(360%(180-a[i])==0) {
cout<<"YES"<<endl;
} else {
cout<<"NO"<<endl;
}
}
return 0;
}
解析:虽然说这个代码上交是正确的,但是在我的编译器验证119的时候还是显示"NO"的,但是提交上去就是"YES",不知道为什么。
556A.Case of the Zeros and Ones
这题一看以为和字符串的操作有关,其实就是一道简单的数学题。
代码:
#include<iostream>
#include<string.h>
#include<cstdio>
#include<set>
#include<memory.h>
#include<algorithm>
#include<vector>
#include<math.h>
#include<queue>
#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<n;i++) {
cin>>a[i];
if(a[i]=='0') {
num0++;
} else if(a[i]=='1') {
num1++;
}
}
ci=min(num0,num1);
cout<<n-ci*2<<endl;
return 0;
}
解析:统计出0和1的数量,选出较小者进行删减即可;
476A.Dreamoon and Stairs
这题暴力法解决,求出每步都走2时的步数,如果最后一步不足2,就走1步,然后判断这时的步数能不能被m整除,不行就把2变成1+1,如果全部都变成1还是不能满足就输出-1;
代码:
#include<iostream>
#include<string.h>
#include<cstdio>
#include<set>
#include<memory.h>
#include<algorithm>
#include<vector>
#include<math.h>
#include<queue>
#define LL long long
using namespace std;
const LL maxn=200009;
int n,m,ci,yu;
int main() {
cin>>n>>m;
if(n<m) {
cout<<-1<<endl;
return 0;
}
ci=n/2;
yu=n;
if(yu%2==1) {
ci++;
}
while(ci%m!=0) {
int tmp=ci;
ci++;
tmp--;
if(tmp==0) {
break;
}
}
if(ci%m==0) {
cout<<ci<<endl;
} else {
cout<<-1<<endl;
}
return 0;
}
478A. Initial Bet
这题只要找到规律就是一道水题,求出平均值,再每个数减去平均值,只要差等于0,这个差就是初始值。
代码:
#include<iostream>
#include<string.h>
#include<cstdio>
#include<set>
#include<memory.h>
#include<algorithm>
#include<vector>
#include<math.h>
#include<queue>
#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<<endl;
return 0;
}
res/=5;
for(int i=0;i<5;i++) {
cha+=c[i]-res;
}
if(cha==0) {
cout<<res<<endl;
} else {
cout<<-1<<endl;
}
return 0;
}
520B - Two Buttons
我的思路:这题一拿到就是使用分情况处理的方法来解决,从n到m,判断n*2和m之间的大小关系,再分情况进行判断,这种方法求出来的次数并不一定是最小的次数。
网上的思路:我们不用n到m的转化,可以从m到n的转化,这样转化就简单很多,直接判断m是否为偶数,是则减半,不是则加一来使它成为偶数。
网上代码:
#include<iostream>
#include<string.h>
#include<cstdio>
#include<set>
#include<memory.h>
#include<algorithm>
#include<vector>
#include<math.h>
#include<queue>
#define LL long long
using namespace std;
const LL maxn=200009;
int n,m;
int res;
int main() {
cin>>n>>m;
while(n<m) {
if(m%2) {
m++;
} else {
m/=2;
}
res++;
}
cout<<res+n-m<<endl;
return 0;
}
474B - Worms
这题逻辑十分简单,直接判断数在哪个区间内,但是问题是时间复杂度的问题。
我的代码:
#include<iostream>
#include<string.h>
#include<cstdio>
#include<set>
#include<memory.h>
#include<algorithm>
#include<vector>
#include<math.h>
#include<queue>
#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<n;i++) {
cin>>a[i];
}
cin>>m;
for(int i=0;i<m;i++) {
cin>>q[i];
}
for(int i=0;i<m;i++) {
int k=0,j=0;
while(q[i]>(j+a[k])) {
j+=a[k];
k++;
}
cout<<k+1<<endl;
}
return 0;
}
解析:这个代码是会超时的,因为每次来一个数就要从第一个区间开始判断,所以我的更改代码是给q数组排序,但是这样输出的顺序就不同,也不行
网上的思路:使用另一个数组来存放区间数,在输入的时候直接判断在哪个区间;
网上代码:
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
using namespace std;
int com[1000008];
int main()
{
int n;
while(cin>>n)
{
int a[100008];
for(int i=0; i<n; i++)
cin>>a[i];
for(int i=1; i<n; i++)
a[i]+=a[i-1];
int flag=0;
for(int i=0; i<=a[n-1]; i++)
com[i]+=(i<=a[flag]?flag:++flag)+1;
int m;
cin>>m;
while(m--)
{
int temp;
cin>>temp;
cout<<com[temp]<<endl;
}
}
return 0;
}
//网上代码,测试2
我按网上代码写的代码:
#include<iostream>
#include<string.h>
#include<cstdio>
#include<set>
#include<memory.h>
#include<algorithm>
#include<vector>
#include<math.h>
#include<queue>
#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<n;i++) {
cin>>a[i];
}
for(int i=1;i<n;i++) {
a[i]+=a[i-1];
}
int index1=0;
for(int i=0;i<=a[n-1];i++) {
q[i]+=(i<=a[index1]?index1:++index1)+1;
}
cin>>m;
while(m--)
{
int temp;
cin>>temp;
cout<<q[temp]<<endl;
}
}
return 0;
}
这两个一样的代码,为什么我的就是不行呢??
37A - Towers
这题很简单,就是一开始理解不了题意,题意是找出数组最大的重复数和一共存在多少个不同的数;
// sub.cpp: 定义控制台应用程序的入口点。
//
#include<iostream>
#include<string.h>
#include<cstring>
#include<cstdio>
#include<set>
#include<memory.h>
#include<algorithm>
#include<vector>
#include<math.h>
#include<queue>
#include<map>
#define LL long long
using namespace std;
LL GCD(LL a, LL b) {
if (a<b) {
swap(a, b);
}
while (a%b) {
LL tmp = a;
a = b;
b = tmp % b;
}
return b; //最大公约数
}
LL LCM(LL a, LL b) {
LL tmp = GCD(a, b);
LL res = a * b / tmp;
return res; //最小公倍数
}
int BinarySort(vector<int> 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<x;i++) {
if (x%i == 0) {
return false;
}
}
return true;
}
void f(int a, int b) {
a -= 2;
b++;
}
const int maxn = 10005;
int a[maxn], b[maxn];
int n, c;
int main() {
cin >> 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