CSP-J 2022 游记

一、复赛经历(题解) 

第一题

pow

题目描述

小文同学刚刚接触了信息学竞赛,有一天她遇到了这样一个题:给定正整数a 和b,求a b 的值是多少。
a b 即b个a 相乘的值,例如 23即为3 个 2 相乘,结果为2 × 2 × 2 = 8。
“简单!”小文心想,同时很快就写出了一份程序,可是测试时却出现了错误。
小文很快意识到,她的程序里的变量都是 int 类型的。在大多数机器上, int 类型能表示的最大数为231 -1 ,因此只要计算结果超过这个数,她的程序就会出现错误。
由于小文刚刚学会编程,她担心使用 int 计算会出现问题。因此她希望你在 ab的值超过 109 时,输出一个 -1 进行警示,否则就输出正确的ab的值。
然而小文还是不知道怎么实现这份程序,因此她想请你帮忙。

输入描述

从文件 pow.in 中读入数据。
输入共一行,两个正整数a,b。

输出描述

输出到文件 pow.out 中。
输出共一行,如果ab 的值不超过 109 ,则输出ab 的值,否则输出 -1 。

样例1

输入 复制

10 9

输出

1000000000

样例2

输入 复制

23333 66666

输出

-1

提示

对于10%的数据,保证b = 1。
对于30%的数据,保证b ≤ 2。
对于60%的数据,保证b ≤ 30 , a b ≤1018。
对于100%的数据,保证1 ≤ a, b ≤ 109。
本题需要使用文件输入输出,而非标准输入输出。
freopen("pow.in","r",stdin);
freopen("pow.out","w",stdout);

解析

这是一道水题,但也有一个bug需要注意,就是当输入为1 10^9时,如果不特判,循环就会真的执行10^9次,很明显,这样肯定会超时,只要加一个特判就好啦(经验算,当输入为2 10^9时循环只执行30次不到,log的复杂度)。

 考场100分代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
	freopen("pow.in","r",stdin);
	freopen("pow.out","w",stdout);
	ll a,b; scanf("%lld%lld",&a,&b);
	ll ans=1;
	if(a==1){
		printf("1");
		return 0;
	}
	for(ll i=1; i<=b; i++){
		ans*=a;
		if(ans>1e9){
			printf("-1");
			return 0;
		}
	}
	printf("%lld",ans);
	return 0;
}

第二题

decode

题目描述

给定一个正整数 k,有k 次询问,每次给定三个正整数ni , ei , di ,求两个正整数 pi ,qi ,使ni = pi ×qi 、ei ×di = (pi − 1) (qi − 1) + 1

输入描述

从文件 decode.in 中读入数据。
第一行一个正整数 k,表示有 k 次询问
接下来 k 行,第 i 行三个正整数ni , di , ei ,

输出描述

输出到文件 decode.out 中。
输出 k 行,每行两个正整数pi ,qi 表示答案。
为使输出统一,你应当保证pi ≤ qi
如果无解,请输出 NO .

样例1

输入 复制

10 770 77 5 633 1 211 545 1 499 683 3 227 858 3 257 723 37 13 572 26 11 867 17 17 829 3 263 528 4 109

输出

2 385 NO NO NO 11 78 3 241 2 286 NO NO 6 88

提示

【样例 2】
见选手目录下的 decode/decode2.in 与 decode/decode2.ans。
【样例 3】
见选手目录下的 decode/decode3.in 与 decode/decode3.ans。
【样例 4】
见选手目录下的 decode/decode4.in 与 decode/decode4.ans。

【数据范围】
以下记 m=n - e × d + 2 。
保证对于100%的数据,1 ≤ k ≤ 105 ,对于任意的 1 ≤ i ≤ k , 1 ≤ ni ≤ 1018 ,1 ≤ ei ×di ≤ 1018 , 1 ≤ m ≤ 109

测试点编号k\lek≤n\len≤m\lem≤特殊性质
1110^310310^310310^3103保证有解
2210^310310^310310^3103
3310^310310^91096\times10^46×104保证有解
4410^310310^91096\times10^46×104
5510^310310^910910^9109保证有解
6610^310310^910910^9109
7710^510510^18101810^9109保证若有解则p=q
8810^510510^18101810^9109保证有解
9910^510510^18101810^9109
101010^510510^18101810^9109

本题需要使用文件输入输出,而非标准输入输出。
freopen("decode.in","r",stdin);
freopen("decode.out","w",stdout);

解析

考试前两天刚学的一元二次方程,还不太熟练,就用了二分答案,整道题就变得很烦,还出了个bug,数据卡精度被扣了10分。

这里发一下线性的一元二次方程求根公式法吧(100分)(90分的二分代码找不到了):

(P.S.:

求根公式:对于一元二次方程ax^{2}+bx+c=0 (a\neq 0,b^{2}-4ac\geq 0),x=\frac{-b\pm \sqrt{b^{2}-4ac}}{2a})

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
    ll k; scanf("%lld",&k);
    while(k--){
        ll n,d,e; scanf("%lld%lld%lld",&n,&d,&e);
        ll m=n-e*d+2;
        ll delta=m*m-4*n;
        if(delta<0){
            printf("NO\n");
            continue;
        }
        ll s=sqrt(delta);
        if(s*s==delta && (m+s)%2==0)
            printf("%lld %lld\n",(m-s)/2,(m+s)/2);
        else printf("NO\n");
    }
    return 0;
}

至于三四两题,像我这样的蒟蒻就不用想了。第三题可以骗分,通过性质1、2至少可以骗到35分(在面对极强的估分数据时),且可在10分钟内打完,但作为蒟蒻,考场上大半的时间都用在修前两题的bug上了,根本打不完,最后只好骗了十分。第四题有思路但不会写,大致就是先给点排序,然后依次枚举以该点为终点的序列最大长度(枚举到前面能到达的每个点的距离加上前面对应点的序列最大长度求最大值)(DP),最后随便输出了一个10骗了5分。

二、总结

复赛已过两个月,反思了很多不足,在不断刷题中(尤其是DP)……最后得了100+90+10+5=205,作为在浙江省的悲惨考生,只拿了一个二等,不过比起我去年差半分进复赛,还是要好的多了……(去年浙江省66分进复赛,我65.5……)唉,都是泪。不说了。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值