T1 小苹果
题目大意
小明小红是损友,小红偷小明的苹果,但是不想让他看出来,于是间隔着偷,每次间隔两个,然后把剩下的拼起来,问一共要偷几次,第n个苹果是几次偷完的。
思路
首先看到这个题目,我们直接想到暴力模拟,没错用最简单的模拟就直接能过,设定好终止条件就好。
代码
比较简单,100pt:
#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
int n,x;
int ans,cnt;
int main(){
cin >> n;
x=n;
while(x){
cnt++;
x-=(x+2)/3;
}
cout << cnt << ' ';
while(1){
ans++;
if(n%3==1)break;
n-=(n+2)/3;
}
cout << ans << endl;
}
T2 公路
题目大意
小明开车自驾游,沿着一条公路跑,每加一点油就能跑一段路,问从1~n最少需要加多少油。
思路
首先注意到从1~n,吓得我一激灵想要用dp,但是想想不对,这道题显然是可以贪心的,但是贪心的方式不一样,我自己写出来的时候都感觉不像贪心,看题解说这叫做反悔贪心,简单来说就是没油了就从前面的最便宜的地方加油,可以理解为小明有一个传送器,可以跑到前面加一次油再传送回来(不然就要跑冤枉路了),很好理解的算法,代码也不长。
代码
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int N = 1e5 + 10;
int v[N], a[N];
int n, d;
int main() {
scanf("%d%d", &n, &d);
for (int i = 1; i < n; i++) scanf("%d", &v[i]);
int mi = 1e9;
LL ans = 0, s = 0;
for (int i = 1; i < n; i++) {
scanf("%d", &a[i]);
s += v[i];
mi = min(mi, a[i]);
if (s > 0) {
ans += (s + d - 1) / d * mi;
s -= (s + d - 1) / d * d;
}
}
printf("%lld\n", ans);
return 0;
}
T3 一元二次方程
题目大意
围绕着一元二次方程求根公式展开一系列非常复杂的模拟,完全说不清楚,直接贴上原题链接:
P9750 [CSP-J 2023] 一元二次方程 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
思路
一道非常典型,非常豪堪,非常令人眼前一黑的,非常大的模拟题!
首先我们发现这道题是要不断的计算计算再计算,计算出来的情况怎么搞都完全不会超过时间限制,因为数据范围只有5000次询问而最大的M也就只有1000,所以考虑直接进行模拟,模拟的过程中需要不断的特判,这一题我做出来了结果传上去只有60pt,后来测样例找到了一个bug,de掉了以后仍然是60pt,于是我怒看题解,题解的代码比我少一半……好吧,我干脆直接把我的代码和题解的代码都贴上来得了。
代码
我的 60pt:
#include<bits/stdc++.h>
#define endl '\n'
//#define int double
using namespace std;
int t,m,a,b,c;
bool check(double n){
int m=int(n);
if(n == m){
return 1;
}
return 0;
}
int f(int n){
for(int i=sqrt(n); i>=2; i--){
if(n%(i*i) == 0){
return i;
}
}
return 1;
}
int main(){
// freopen("uqe.in","r",stdin);
// freopen("uqe.out","w",stdout);
cin >> t >> m;
for(int i=1; i<=t; i++){
cin >> a >> b >> c;
if(a < 0){
a = -a;
b = -b;
c = -c;
}
if(b*b-4*a*c < 0){
cout << "NO" << endl;
continue;
}
else{
int z = b*b-4*a*c;
// cout<<"z="<<z<<endl;
double x = (b*(-1)+sqrt(z))/(2*a);
// cout<<"x="<<x<<endl;
if(check(sqrt(z)) == 1){
if(check(x) == 1){
if(x == 0){
cout << 0 << endl;
}
else{
cout << x << endl;
}
}
else{
int n = -b+sqrt(z);
int m = 2*a;
// cout<<"__gcd(n,m)="<<__gcd(n,m)<<endl;
cout << n/abs(__gcd(n,m)) << "/" << m/abs(__gcd(n,m)) << endl;
}
}
else{
double q1 = (b*1.0/(2*a))*-1;
// cout<<"q1="<<q1<<endl;
double q2 = 1/(2*a);
// cout<<"q2="<<q2<<endl;
int d = f(z);
// cout<<"d="<<d<<endl;
if(q1 == -0){
q1 = 0;
}
if(q1 != 0){
if(check(q1) == 1){
cout << q1;
}
else{
int n = (b*1.0)*-1;
int m = 2*a;
// cout<<"__gcd(n,m)="<<__gcd(n,m)<<endl;
cout << n/abs(__gcd(n,m)) << "/" << m/abs(__gcd(n,m));
}
cout<<"+";
}
if(q2 == 1){
cout<<sqrt(z)<<endl;
}
else if(check(q2) == 1){
double s=d*1.0/(2*a);
if(check(s) == 1){
if(s == 1) cout << "sqrt(" << z/(d*d) << ")" << endl;
else cout << s << "*sqrt(" << z/(d*d) << ")" << endl;
}
else{
if(__gcd(d,2*a) == 1){
if(d != 1)
{
cout<<d <<"*";
}
cout << "sqrt(" <<z/(d*d)<< ")/"<< 2*a<< endl;
}
else{
cout << "sqrt(" <<z/(d*d)<< ")/"<< 2*a/__gcd(d,2*a)<< endl;
}
}
}
}
}
}
}
题解 100pt:(诡异的代码)
#include<bits/stdc++.h>
using namespace std;
int T,m,a,b,c,d,k,t;
int gcd(int a,int b){//最大公因数
return b?gcd(b,a%b):a;
}
void Main(){
cin>>a>>b>>c;
if(a<0)
a=-a,b=-b,c=-c;//细节1:分母非负
d=b*b-4*a*c,k=1;//d是delta
if(d<0){
cout<<"NO\n";
return;
}//无解
for(int i=2;i*i<=d;i++)
while(d%(i*i)==0)
k*=i,d/=(i*i);//k*sqrt(d)
if(d==0||d==1){//有理数
t=abs(gcd(2*a,-b+k*d));//细节2:取绝对值
cout<<(-b+k*d)/t;
if(2*a/t!=1)//细节3:分母非1
cout<<'/'<<2*a/t;
cout<<'\n';
return;
}
//-b/2a+k*sqrt(d)/2a
t=abs(gcd(-b,2*a));//细节2
if(-b/t==0)//细节4:不能有0+xxx
goto g;
cout<<-b/t;
if(2*a/t!=1)//细节3
cout<<'/'<<2*a/t;
cout<<'+';
g:
t=abs(gcd(k,2*a));//细节2
if(k/t!=1)//细节5:乘数不为1
cout<<k/t<<'*';
cout<<"sqrt("<<d<<')';
if(2*a/t!=1)//细节3
cout<<'/'<<2*a/t;
cout<<'\n';
return;
}
int main(){/*
freopen("uqe.in","r",stdin);
freopen("uqe.out","w",stdout);*/
for(cin>>T>>m;T;--T)
Main();//根据某人言,多测函数好
return 0;
}