CSP-J模拟赛day2——解析+答案

题目传送门

气球条幅 balloon

题解

将气球和条幅都从小到大排序就行,然后一个一个的匹配

Code

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
long long a[maxn],b[maxn];
int main(){
	//freopen("balloon.in","r",stdin);
	//freopen("balloon.out","w",stdout);
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%lld%lld",&a[i],&b[i]);
	}
	sort(a+1,a+n+1);
	sort(b+1,b+n+1);
	long long ans=0,cnt=1;
	for(int i=1;i<=n;i++){
		if(a[i]>=b[cnt]){
			ans++;
			cnt++;
		}
	}
	printf("%lld",ans);
	return 0;
}

实数集合 real

题解

大于1的正数都要取,负数要选的话就要一次性选两个

Code

#include <bits/stdc++.h>
using namespace std;
int a[10005];//最后答案 
bool flag[10005];//标记数组 

struct tt{
    double a;
    int pos;
} t[10005];//存储数组 

bool cmp(tt a, tt b){//比较器 
    return a.a < b.a;//从小到大进行枚举 
}
int main(){
    int m,cas,n,k;
    cin>>cas;
    while (cas--){
    	//初始化 
        memset(a, 0, sizeof(a));//清空数组 
        memset(flag, 0, sizeof(flag)); 
        memset(t, 0, sizeof(t));
        cin>>n;
        for (int i=1;i<=n;i++){
        	cin>>t[i].a;
            t[i].pos=i;//记录编号 
        }
        sort(t+1,t+n+1,cmp);//排序 
        int cnt = 0;
        for (int i=1;i<=n;i++){
			if (t[i].a<0)cnt++;//记录负数的个数 
		} 
            
        for (int i=1;i<=cnt;i++){//枚举负数 
        	if (!flag[i]){//如果当前这个点 
        		if (t[i].a * t[i + 1].a > 1 + 1e-6){//判断这两个数相乘是否大于1
					//如果成功,则选择 
                    flag[i]=true;
					flag[i+1]=true;
                }
			}       
		}
             
        for (int i=cnt;i<=n;i++){//如果是正数,则需要大于1才可以选择 
			if (t[i].a >1+1e-6){
				flag[i]=true;
			}
        } 
        cnt=0;//清空cnt,为后面存答案做准备 
        for (int i=1;i<=n;i++){//存储答案 
        	if (flag[i]){
                cnt++;
                a[cnt]=t[i].pos;
            }
		}
            
        sort(a+1,a+cnt+1);//按照编号的顺序从小到大进行排序 

        if (cnt==0){//如果一个都没有选择则进行特判 
            if (n==1){//如果只有一个数 
                cout<<1<<endl<<1<< endl;
            }
            else{
            	//否则选择最小的两个数和一个最大数 
                double tmp=t[1].a*t[2].a;
                double tmp2=t[n].a;
                if (tmp>tmp2+1e-6){//如果两个数的乘积大于一个数 
                    int a=t[1].pos;
                    int b=t[2].pos;
                    //按照编号从小到大进行排序 
                    if (a>b)cout<<2<<endl<<b<<" "<<a<<endl;
                    else cout<<2<<endl<<a<<" "<<b<<endl;
                }
                else cout<<1<<endl<<t[n].pos<<endl;//如果一个数大于两个数的乘积 
            }
        }else {//如果有选择,则正常输出 
        	cout<<cnt<<endl;
       		for(int i=1;i<=cnt;i++){
       			cout<<a[i]<<" ";
			}
			cout<<endl;
		}
    }
    return 0;
}

十六 sixteen

题解

通过记录前缀来判断,并且枚举截断点

Code

#include <bits/stdc++.h>
using namespace std;
#define LL long long 

string s;
int p, q;
const int N = 1e7 + 100;
LL l[N], r[N];//记录前缀和后缀 

int num(char c){//十六进制转十进制 
    if (c>='0'&&c<='9')return c-'0';
    else return c-'a'+10;
}
int main(){
    cin>>s;
    cin>>p>>q;
    int len=s.length();//记录长度 

    for (int i=0;i<len;i++){
        l[i]=(l[i-1]*16+num(s[i]))%p;//根据取余算法进行前缀和 
    }
    LL tmp=1;//记录当前的幂 
    for (int i=len-1;i>=0;i--){
        r[i]=(r[i+1]+num(s[i])*tmp)%q;//记录后缀 
        tmp=(tmp*16)%q;//当前指数并取余 
    }
    int cnt=0;//记录答案 
    for (int i=1;i<len-2;i++){//枚举断点 
    	if (l[i]==0&&r[i+1]==0&&s[i+1]!='0'){//如果条件成立 
            cnt++;
        }
	}
        
    if (l[len-2]==0&&r[len-1]==0)cnt++;//特判 
    cout<<cnt;
    return 0;
}

飞翔 flappy

题解

记录能到达的最高点和最低点,如果最高点小于最低点就不行,然后从后往前进行模拟

Code

#include <bits/stdc++.h>
using namespace std;
int n, v;
int up[1000100], down[1000100], maxv[1000100], minv[1000100];//maxv和minv记录最小的上限和最大的下限 
int main(){
	cin>>n>>v;
    for (int i=1; i <= n; i++){
    	cin>>down[i]>>up[i];
    }
    maxv[0]=minv[0]=v;//初始条件 
    for (int i=1;i<=n;i++){
        maxv[i]=min(maxv[i-1]+1,up[i]);//比较上一位+1和当前位 
        minv[i]=max(minv[i-1]-1,down[i]);
        if (maxv[i]<minv[i]){//如果上限比下限小 
        	cout<<"impossible"<<endl<<i;//那么就一定不可以 
            return 0;
        }
    }

    long long sum=maxv[n];//从后往前进行推 
    for (int i= n-1;i>=1;i--){
        if (maxv[i+1]+1<maxv[i])maxv[i]=maxv[i+1]+1;//如果方案明显达不到,就更新 
        sum+=maxv[i];//加上上边界 
    }
    cout<<sum<<endl;
    return 0;
}
  • 10
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值