成信大天梯赛
L1-6 二进制
因为二进制是逢二进一,所以我们只要用cnt记录一下每一位上的数并给它加起来,然后cnt%2便是其和这一位上的数,注意要从右往左开始
点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
void solve()
{
string a,b;
cin>>a>>b;
string res;
int i=a.size()-1,j=b.size()-1;
int cnt=0;
while(i>=0||j>=0||cnt){//注意cnt这个条件
cnt+=(i>=0)?a[i--]-'0':0;//别忘了i--,j--
cnt+=(j>=0)?b[j--]-'0':0;
res.push_back(cnt%2+'0');//这边记得加‘0’
cnt/=2;//别忘了除2
}
reverse(res.begin(),res.end());
cout<<res;
}
signed main()
{
solve();
}
L1-8 堆积木
这一题是个好题,我们要学习一个思想,把一些可以舍弃的数据舍弃掉,比如在这一题里面,每一个积木只跟上一个积木有关系,所以我们只用一个数组格便可以代表一个塔,可以将上上个覆盖掉,同样是stl的模拟题,还是要多练多练,下列代码有详细的注解
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
void solve()
{
//做这种题首先要思考用什么容器来模拟题意
vector<int>ve;//一个存塔的数量
vector<int>he;//一个存高度
int n;
cin>>n;
while(n--)
{
int x;
cin>>x;
if(ve.size()==0){//如果没有塔就新建一个塔
ve.push_back(x);
he.push_back(1);
}
else{
int pos=-1,minn=1e9;//pos用来实现位置的更新
//有塔就遍历塔找符合的
for(int j=0;j<ve.size();j++)
{
if(ve[j]>x){
int temp=ve[j]-x;
if(temp<minn)
{
pos=j;
minn=temp;
}
else if(temp==minn){//如果差值相同就放在最高的上面
if(he[j]>he[pos]){
pos=j;
}
}
}
}
if(pos==-1){// 没有找到
ve.push_back(x);
he.push_back(1);
}
else{//找到了直接覆盖这个塔顶,因为下一个状态只跟当前的这个有关
ve[pos]=x;
he[pos]++;
}
}
}
int ans=0;
for(int i=0;i<ve.size();i++) ans=max(he[i],ans);
cout<<ans<<" "<<ve.size()<<endl;
}
signed main()
{
solve();
}
天梯赛训练
P2669 [NOIP2015 普及组] 金币
这确实是一道简单题,但是如果你没处理好,可能会很浪费你的时间,这题给了我一个启发,就是把平方的归为一部分,其他的再加上去
点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
#define int long long
void solve()
{
int n,sum=0,temp=1,cnt=1,last=0;
cin>>n;
while(1)
{
if(cnt>n) break;
sum+=temp*temp;
temp++;
last=cnt;
cnt+=temp;
}
if(last!=n){
sum+=(n-last)*temp;
}
cout<<sum;
}
signed main()
{
solve();
return 0;
}
点击查看代码
#include<iostream>
using namespace std;
int main()
{
int a,b=0,c=1,i;//a为天数,b为金币,c为每天比原来每天多获得的金币数
cin>>a;
for(i=1;i<=a;i++)
a-=i,b+=c*c,c++;//金币每天加上c的2次方,天数当然要减i了
cout<<b+a*c;//最后算上剩余的a乘加的最多一次的c
return 0;
}
P7071 [CSP-J2020] 优秀的拆分
先打个表把2的1到24次方打印出来,然后一个数我们从2的24次方开始遍历,遇到比他小的第一个数我们就减掉然后跳出循环,然后变成一个新的数以后再找第一个比它小的数以此下去
点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
#define int long long
char c[105][105];
int dx[]={-1,-1,0,1,1,1,0,-1},dy[]={0,1,1,1,0,-1,-1,-1};
int a[25],b[25][25];
void solve()
{
for(int i=1;i<=24;i++) a[i]=(int)pow(2,i);
int n;
cin>>n;
if(n%2==1) cout<<"-1";
else{
while(n>0)
{
for(int i=24;i>=1;i--){
if(a[i]<=n){
cout<<a[i]<<" ";
n-=a[i];
break;
}
}
}
}
}
signed main()
{
solve();
return 0;
}
P2058 [NOIP2016 普及组] 海港
这一题我们用set来存国籍的种类,用map来存国籍的人数,用一个存放pii的优先队列(会按点的第一个值来自动排序)来存每次每个国籍加入的时间,当时间超过了86400的时候我们便把优先队列中的这个时间对应的国籍删掉,对应的map中的这个国籍人数也要减,当对头对应的map中的国籍的人数为1的时候,set就除去这个国籍
点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
#define int long long
char c[105][105];
int dx[]={-1,-1,0,1,1,1,0,-1},dy[]={0,1,1,1,0,-1,-1,-1};
int a[25],b[25][25];
set<int> se;
priority_queue<pii,vector<pii>,greater<pii> >q;
unordered_map<int,int>mp;
void solve()
{
int n,m;
cin>>n>>m;
while(m--)
{
int x;
cin>>x;
q.push({n,x});
mp[x]++;
se.insert(x);
}
while(n-q.top().first>=86400)
{
auto k=q.top();
q.pop();
if(mp[k.second]==1) se.erase(k.second);
mp[k.second]--;
}
cout<<se.size()<<endl;
}
signed main()
{
int t;
cin>>t;
while(t--)solve();
return 0;
}
专题训练
还没复盘完毕
标签:0324,cnt,temp,int,题解,pos,long,--,0318 From: https://www.cnblogs.com/swjswjswj/p/18092460