J组题
2026-10-21 20:29:14
发布于:上海
[CSP-J 2022] 乘方
求 ab 的函数:pow(a, b),返回值是 double 类型。数据范围(整数)是:1e16
求比较大的 ab 的方法:用循环一个个累乘计算。即,求 b 个 a 相乘的运算。
#include<iostream>
using namespace std;
int main(){
int a, b;
cin >> a >> b;
long long sum = a;
//!!!!!!非常不严谨,存在问题
//① 看题,第一步看数据范围
//② 写题,第一步想我会不会超时
if(a == 1){
cout << 1;
return 0;
}
for(int i = 2; i <= b; i++){
if(sum * a > 1000000000){
cout << "-1";
return 0;
}
sum *= a;
}
cout << sum;
return 0;
}
[CSP-J 2022] 解密
通过对题目中两个公式的变形,可以得到两个式子:p + q = n - ed + 2,p * q = n
法一:二次方程的求根公式和韦达定理算法 p 和q
法二:
考虑枚举 p 和 q,在 [1, n - ed + 2] 的范围内枚举,这个时间复杂度是 O(nk),一定会超时。
所以考虑用二分枚举 p,用 p * q = n 验证范围。
#include <bits/stdc++.h>
#define int long long
using namespace std;
signed main() {
int k;
cin >> k;
while (k--) {
int n, d, e;
cin >> n >> d >> e;
int m = n - d * e + 2;
// 二分找 p,范围 [1, m/2]
int lo = 1, hi = m;
int ans = -1;
while (lo <= hi) {
int mid = (lo + hi) / 2;
int val = mid * (m - mid);
if (val == n) {
ans = mid;
break;
} else if (val < n) {
lo = mid + 1;
} else {
hi = mid - 1;
}
}
if (ans == -1) {
cout << "NO\n";
} else {
cout << ans << " " << m - ans << "\n";
}
}
return 0;
}
[CSP-J 2023] 一元二次方程
遇到模拟,先考虑怎么分类讨论。
分类讨论的依据是,方程的解的情况,解:无实数解,有实数解(有两个相同的实数解,有两个不同的实数解)
令delta = b*b - 4*a*c;
delta < 0(没用实数解)
-> 输出 NO
delta == 0(有相同的解)
-> 化简输出-(b/2a)
为什么要化简???b = 4, a = 2,输出-(2/4) ??????????
delta > 0(有不同的解)
输出化简之后的max((-b + sqrt(delta))/ 2a, (-b - sqrt(delta)) / 2a)
#include<bits/stdc++.h>
using namespace std;
int t, m;
// 求最大公约数,用于分数化简
int gcd(int a, int b) {
if (b == 0) return a;
return gcd(b, a % b);
}
void solve() {
int a, b, c;
cin >> a >> b >> c;
// 统一处理a为正,方便分母处理
if (a < 0) a = -a, b = -b, c = -c;
int delta = b * b - 4 * a * c;
// 情况1:Δ < 0,无实数解
if (delta < 0) {
cout << "NO" << endl;
}
// 情况2:Δ = 0,有重根
else if (delta == 0) {
int t = gcd(abs(2 * a), abs(b)); // 求分子分母的最大公约数
int fz = (-1) * b / t; // 化简后的分子
int fm = 2 * a / t; // 化简后的分母
if (fz == 0) cout << 0 << endl;
else {
if (fz % fm == 0)
cout << fz / fm << endl; // 整数解
else
cout << fz << "/" << fm << endl; // 分数解
}
}
// 情况3:Δ > 0,有两个不同实根
else {
int de = sqrt(delta);
// 子情况3.1:Δ是完全平方数,解为有理数
if (de * de == delta) {
// 取较大的解:当a>0时取+号,a<0时取-号(但前面已处理a>0)
int fz = -b + de; // 分子
int fm = 2 * a; // 分母
int t = gcd(abs(fz), abs(fm));
fz /= t, fm /= t;
if (fz == 0) cout << 0 << endl;
else {
if (fz % fm == 0)
cout << fz / fm << endl;
else
cout << fz << "/" << fm << endl;
}
}
// 子情况3.2:Δ不是完全平方数,解为无理数
else {
int r = 1;
// 提取Δ的最大平方因子
for (int i = sqrt(delta); i >= 1; i--) {
if (delta % (i * i) == 0) {
r = i;
break;
}
}
int t1 = gcd(abs(b), abs(2 * a)); // 有理部分的化简因子
int t2 = gcd(abs(r), abs(2 * a)); // 无理部分的化简因子
// 输出有理部分:-b/(2a)
if (b != 0) {
if ((-b) % (2 * a) != 0) {
// 输出分数形式
cout << (-b) / t1 << "/" << (2 * a) / t1;
} else {
// 输出整数形式
cout << (-b) / (2 * a);
}
cout << "+"; // 有无理部分,需要加号
}
// 输出无理部分:(r/(2a)) * √(delta/(r²))
int inside = delta / (r * r); // 根号内的数
if (r % (2 * a) == 0) {
int coeff = r / (2 * a);
if (coeff != 1)
cout << coeff << "*";
cout << "sqrt(" << inside << ")";
}
else if ((2 * a) % r == 0) {
int denom = (2 * a) / r;
cout << "sqrt(" << inside << ")/" << denom;
}
else {
int num_part = r / t2;
int denom_part = (2 * a) / t2;
if (num_part != 1)
cout << num_part << "*";
cout << "sqrt(" << inside << ")/" << denom_part;
}
cout << endl;
}
}
}
int main() {
cin >> t >> m;
while (t--) {
solve();
}
return 0;
}
这里空空如也



















有帮助,赞一个