sicnu 区域赛选拔赛

时间:2023-02-13 20:54:36

首先是a题,模拟直接求每个点成功的概率

数据规模较小,听说有规律是(n+1)*p

题目链接:https://acm.sicnu.edu.cn/problem/Contest_18_A

#include <bits/stdc++.h>
#define INF 1e-8
using namespace std;

int main(){
    int n,a,b;
    cin>>n>>a>>b;
    double maxx=-1;
    double p=a*1.0/b;
    int maxk=1;
    for(int k=0;k<=n;k++){
        double s=1.0;
        for(int i=n;i>=(n-k+1);i--)
            s*=i*1.0;
        for(int j=1;j<=k;j++) s/=j*1.0;
        for(int i=1;i<=k;i++) s*=p;
        for(int i=1;i<=n-k;i++) s*=(1-p);
        if(s>maxx||fabs(s-maxx)<=INF){
            maxx=s;
            maxk=k;
        }
        //cout<<s<<endl;
    }
    cout<<maxk<<endl;
    return 0;
}

b题 ,裸拓扑排序,比赛的时候看都没看,有点难受

题目链接:https://acm.sicnu.edu.cn/problem/Contest_18_B

#include <bits/stdc++.h>
using namespace std;
int g[105][105];
int dist[105];
int vis[105];
int n,m;
void sort_(){
    queue<int> num;
    map<int,int> vis;
    for(int i=1;i<=n;i++) if(dist[i]==0) {num.push(i);vis[i]++;}
    int count=0;
    while(!num.empty()){
        int t=num.front();
        num.pop();
        count++;
        for(int i=1;i<=n;i++){
            if(g[t][i]==1){
                g[t][i]=0;
                dist[i]--;
            }
            if(dist[i]==0&&vis[i]==0) {num.push(i);vis[i]++;}
        }
    }
    if(count==n) cout<<"Yes"<<endl;
    else cout<<"No"<<endl;
}
int main()
{
    int t,k,a;
    memset(g,0,sizeof(g));
    memset(dist,0,sizeof(dist));
    cin>>n>>m;
    for(int i=0;i<m;i++){
        cin>>t>>k;
        for(int j=0;j<k;j++){
            cin>>a;
            if(g[t][a]==0){
                g[t][a]=1;
                dist[a]++;
            }
        }
    }
    sort_();
    return 0;
}

c题,一眼看过去就像傻逼题,但是wa了超级多次,首先是爆int了,没注意,然后是t和s的大小关系,题目中没有明确的确定

题目链接:https://acm.sicnu.edu.cn/problem/Contest_18_C

#include <bits/stdc++.h>
using namespace std;
struct node{
    unsigned long long a,b;
    long long v;
}num[100005];
int cmp(node x,node y){
    return x.v<y.v;
}
int main()
{
    int n,s,t;
    int x0,y0,z0;
    int x,y,z;
    int flag=0;
    //freopen("e://duipai//data.txt","r",stdin);
    //freopen("e://duipai//out2.txt","w",stdout);
    cin>>n>>s>>t;
    for(int i=0;i<n;i++){
        if(i==0) cin>>x0>>y0>>z0;
        else {
            cin>>x>>y>>z;
            num[i].a=(long long)(x-x0)*(x-x0)+(long long)(y-y0)*(y-y0)+(long long)(z-z0)*(z-z0);
        }
    }
    for(int i=0;i<n;i++){
        if(i==0) cin>>x0>>y0>>z0;
        else {
            cin>>x>>y>>z;
            num[i].b=(long long)(x-x0)*(x-x0)+(long long)(y-y0)*(y-y0)+(long long)(z-z0)*(z-z0);
            if(t>s){
                if(num[i].a>num[i].b) flag=1;
            }
            else {
                if(num[i].a<num[i].b) flag=1;
                else swap(num[i].a,num[i].b);
            }
            if(flag==0) num[i].v=abs(num[i].b-num[i].a);
        }
    }
    //for(int i=1;i<n;i++) cout<<num[i].a<<" "<<num[i].b<<endl;
    if(flag==1) cout<<"No"<<endl;
    else{
        sort(num+1,num+n,cmp);
        for(int i=2;i<n;i++){
            if(num[i].a<num[i-1].a) {
                flag=1;
                break;
            }
            if(num[i].a==num[i-1].a){
                if(num[i].v!=num[i-1].v){
                    flag=1;
                    break;
                }
            }
        }
        if(flag==1) cout<<"No"<<endl;
        else cout<<"Yes"<<endl;
    }
    return 0;
}

d题,拿到题目理解错题意以为这个数字的组成可以是无序的,然后找dp状态数太多了,根本无法优化,比赛的时候就放了

然后比赛后,队友告诉我,这个数字是有序的,直接暴力就行了,难受到爆炸

题目链接:https://acm.sicnu.edu.cn/problem/Contest_18_D

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int main()
{
    int n,m=0;
    int num[100];
    int s[100];
    string s1;
    cin>>n;
    cin>>s1;
    for(int i=0;i<n;i++) s[i]=s1[i]-'0';
    for(int i=0;i<n;i++) m+=s[i];
    int len=0;
    for(int i=2;i<=n;i++){
        if(m%i==0) num[len++]=i;
    }
    for(int i=0;i<len;i++){
        int ans=m/num[i];
        int flag=num[i];
        for(int j=0;j<n;j++){
            if(ans>s[j]) ans-=s[j];
            else if(ans==s[j]) {ans=m/num[i];flag--;}
            else {flag=1;break;}
        }
        if(flag==0){
            cout<<"Yes"<<endl;
            return 0;
        }
    }
    cout<<"No"<<endl;
    return 0;
}

最后一题是最坑的,无限循环小数转分数,一开始的思路是枚举分母,与这个小数相乘,大概估算分子,然后比赛过程中一直wa,可能是枚举的时候数据开小了

比赛完,说是规律题,瞬间炸了,然后推了推,发现确实挺好发现的规律,然后在网上也找到了,证明的方法https://blog.csdn.net/weixin_35653315/article/details/72190641

附上代码吧

#include <bits/stdc++.h>
#define INF 1e-6
using namespace std;
 long long gcd(long long a,long long b){
    return b==0?a:gcd(b,a%b);
 }
int main(){
    long long n=0,m=0,sw=0;
    long long len=1;
    string s;
    cin>>s;
    int vis=0;
    for(int i=2;i<s.length();i++){
        if(s[i]=='(') vis=1;
        if(vis==0){
            n*=10;
            n+=s[i]-'0';
            len*=10;
            sw*=10;
            sw+=s[i]-'0';
        }
        else {
            if(s[i]!='('&&s[i]!=')'){
                m*=10;
                m+=9;
                n*=10;
                n+=s[i]-'0';
            }
        }
    }
    n-=sw;
    m*=len;
    long long t=gcd(n,m);
    cout<<n/t<<"/"<<m/t<<endl;
    return 0;
}