CSP-J2022试题题解

1.乘方

原题:https://www.luogu.com.cn/problem/P8813

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int XN = 1e9;
ll a,b,ans=1;
int main(){
    cin>>a>>b;
    for(int i=1;i<=b;i++){
        ans*=a;
        if(ans>XN){
            cout<<"-1";
            return 0;
        }
    }
    cout<<ans;
    return 0;
}

 

解题思路:

因为pow的速度太慢,所以要使用累乘的方法去判断

 

2.解密

原题:https://www.luogu.com.cn/problem/P8814

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll k,n,d,e;
vector<ll>vec;
pair<ll,ll>ans;
bool Solve(ll n,ll d,ll e){
    for(ll i=1;i*i<=n;i++){
        if(n%i==0){
            vec.push_back(i);
            if(n/i!=i){
                vec.push_back(n/i);
            }
        }
    }
    for(ll i=0;i<vec.size();i+=2){
        if((vec[i]-1)*(vec[i+1]-1)+1==e*d){
            ans.first=vec[i];
            ans.second=vec[i+1];
            return 1;
        }
    }
    return 0;
}
int main(){
    cin>>k;
    while(k--){
        vec=vector<ll>();
        cin>>n>>d>>e;
        if(Solve(n,d,e))cout<<ans.first<<' '<<ans.second<<'\n';
        else cout<<"NO\n";
    }
    return 0;
}

  

题解代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll k,n,e,d,m;
int main(){
    cin>>k;
    while(k--){
        cin>>n>>e>>d;
        m=n-e*d+2;
        ll l=1,r=m/2;
        while(l<r){
            ll mid=(l+r)>>1;
            if(mid*(m-mid)>=n)r=mid;
            else l=mid+1;
        }
        if(m-r>=1&&r*(m-r)==n)cout<<r<<' '<<m-r<<'\n';
        else cout<<"NO\n";
    }
    return 0;
}

  

解题思路:

计算m,使用二分确定第一个数,通过第一个数可以得出第二个数,注意,这道题的数据特别大,需要开long long

错误原因:

想到过二分,却没有坚持自己的思路去走下去,而是选择了因数分解的方式去解题

 

3.逻辑表达式

原题:https://www.luogu.com.cn/problem/P8815

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 3e6+520;
stack<int>num;
stack<char>op;
int cnt1,cnt2,cnt=0;string s;
struct node{
    char op;
    int l,r;
}tree[N];
void creart(){
    int a=num.top();num.pop();
    int b=num.top();num.pop();
    char c=op.top();op.pop();
    if(c=='&')num.push(a&b);
    else if(c=='|')num.push(a|b);
}
void build(){
    for(int i=0;i<s.length();i++){
        if(s[i]=='(')op.push(s[i]);
        else if(s[i]==')'){
            while(op.top()!='(')creart();
            cnt--;
        }else if(s[i]=='&'){
            tree[++cnt].op='&';
            tree[cnt].l=tree[cnt].r=0;
            op.push(s[i]);
        }else if(s[i]=='|'){
            tree[++cnt].op='|';
            tree[cnt].l=tree[cnt].r=0;
            op.push(s[i]);
        }else{
            tree[++cnt].op=s[i];
            tree[cnt].l=tree[cnt].r=0;
            num.push(s[i]-'0');
        }
    }
}
int dfs(int x){
    if(tree[x].op=='0')return 0;
    if(tree[x].op=='1')return 1;
    if(tree[x].op=='&'){
        if(dfs(tree[x].l)==0){
            cnt1++;
            return 0;
        }else return dfs(tree[x].r);
    }
    if(tree[x].op=='|'){
        if(dfs(tree[x].l)==1){
            cnt2++;
            return 1;
        }else return dfs(tree[x].r);
    }
}
int main(){
    cin>>s;
    build();
    int ans=dfs(cnt);
    cout<<ans<<'\n'<<cnt1<<' '<<cnt2;
    return 0;
}

 

题解代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 3e6+520;
map<char,int>yx;
stack<int>num;
stack<char>op;
int cnt1,cnt2,cnt=0;string s;
struct node{
    char op;
    int l,r;
    node(){};
    node(char opv,int ls,int rs){
        op=opv;
        l=ls;
        r=rs;
    }
    node(char opv){
        op=opv;
    }
}tree[N];
void create(){
    int a=num.top();num.pop();
    int b=num.top();num.pop();
    char c=op.top();op.pop();
    tree[++cnt]=node(c,b,a);
    num.push(cnt);
}
void build(){
    for(int i=0;i<s.length();i++){
        if(s[i]=='(')op.push(s[i]);
        else if(s[i]==')'){
            while(op.top()!='(')create();
            op.pop();
        }else if(s[i]=='&'||s[i]=='|'){
            while(op.size()&&yx[op.top()]>=yx[s[i]])create();
            op.push(s[i]);
        }else{
            tree[++cnt]=node(s[i]);
            num.push(cnt);
        }
    }
    while(op.size())create();
}
int dfs(int x){
    if(tree[x].op=='0')return 0;
    if(tree[x].op=='1')return 1;
    if(tree[x].op=='&'){
        if(dfs(tree[x].l)==0){
            cnt1++;
            return 0;
        }else return dfs(tree[x].r);
    }
    if(dfs(tree[x].l)==1){
        cnt2++;
        return 1;
    }
    return dfs(tree[x].r);
}
int main(){
    yx['(']=0;
    yx['&']=2;
    yx['|']=1;
    cin>>s;
    build();
     
//  for(int i=1;i<=cnt;i++){
//      cout<<tree[i].op<<' '<<tree[i].l<<' '<<tree[i].r<<'\n';
//  }
     
    int ans=dfs(cnt);
    cout<<ans<<'\n'<<cnt1<<' '<<cnt2;
    return 0;
}

  

解题思路:

先读入表达式,建立表达式树,通过深搜计算每个“短路”的个数

错误原因:

建树错误,编号传递错误,导致答案错误,且没有运算符的优先级

 

4.上升点列

原题:https://www.luogu.com.cn/problem/P8816

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include<bits/stdc++.h>
#define ll long long
#define x first
#define y second
using namespace std;
const int N = 5e2+255;
pair<int,int>a[N];
int n,K,xdp[N],dp[N],ans,xn=0;
int main(){
    cin>>n>>K;
    for(int i=1;i<=n;i++)cin>>a[i].x>>a[i].y;
    sort(a+1,a+n+1);
    for(int i=1;i<=n;i++){
        int j=i+1;
        if(a[i].y>a[j].y)continue;
        xdp[j]=abs(a[j].x-a[i].x)+abs(a[j].y-a[i].y)-1;
    }
    for(int i=2;i<=n;i++)if(xdp[i])dp[++xn]=xdp[i];
    n=xn;
    for(int i=1;i<=n;i++)dp[i]+=dp[i-1];
    for(int t=1;t<=n;t++){
        for(int i=1;i<=n;i++){
            int j=i+t-1;
            if(j>n)break;
            ans=max(ans,t+(dp[j]-dp[i-1])+(K-(dp[j]-dp[i-1])));
        }
    }
    cout<<ans;
    return 0;
}

  

题解代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include<bits/stdc++.h>
#define ll long long
#define x first
#define y second
using namespace std;
const int N = 5e2+255;
pair<int,int>a[N];
int n,K,dp[N][N],ans;
int main(){
    cin>>n>>K;
    for(int i=1;i<=n;i++)cin>>a[i].x>>a[i].y;
    sort(a+1,a+n+1);
    for(int i=1;i<=n;i++){
        for(int j=0;j<=K;j++){
            dp[i][j]=1;
            for(int k=1;k<i;k++){
                if(a[i].y<a[k].y)continue;
                int dis=(a[i].x-a[k].x)+(a[i].y-a[k].y)-1;
                if(j>=dis)dp[i][j]=max(dp[i][j],dp[k][j-dis]+dis+1);
            }
            ans=max(ans,dp[i][j]+K-j);
        }
    }
    cout<<ans;
    return 0;
}

  

解题思路:

输入每个点的坐标,进行排序,枚举每种组合,组成dp的数据,计算欧几里得距离,取dp的最大值即为答案

错误原因:

思路错误,原代码是前缀和,题解代码是dp算法,导致“听取WA声一片”

posted @   天雷小兔  阅读(159)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示