• Gym .101933 Nordic Collegiate Programming Contest (NCPC 2018) (寒假gym自训第四场)


    (本套题算是比较温和吧,就是罚时有点高。

    B .Baby Bites

    题意:给出一个婴儿给出的数组,有一些数字听不清楚,让你还原,问它是否是一个从1开始的一次增加的数组。

    思路:从左往右依次固定,看是否有矛盾即可。

    #include<bits/stdc++.h>
    #define ll long long
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    #define rep2(i,a,b) for(int i=a;i>=b;i--)
    using namespace std;
    int a[1100]; char c[10];
    int main()
    {
        int N; bool F=true;
        scanf("%d",&N);
        rep(i,1,N) {
            scanf("%s",c+1);
            if(c[1]=='m') a[i]=-1;
            else {
                int L=strlen(c+1);
                rep(j,1,L) a[i]=a[i]*10+c[j]-'0';
            }
        }
        if(a[1]==-1) a[1]=1;
        if(a[1]!=1) F=false;
        rep(i,1,N) {
            if(a[i]==-1&&a[i-1]!=-1) a[i]=a[i-1]+1;
            if(a[i]!=-1&&a[i-1]!=-1)
              if(a[i]!=a[i-1]+1) F=false;
        }
        if(F) puts("makes sense");
        else puts("something is fishy");
        return 0;
    }
    View Code

    C .Code Cleanups

    题意:给定N个物体,每个物品需要在第几天清扫。 你每次可以选择其中几个清扫,但是要满足你选择的集合拖欠的天数之和<20;问最小的清扫次数。

    思路:贪心地取即可。

    #include<bits/stdc++.h>
    #define ll long long
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    int a[1100];
    int main()
    {
        int N,ans=0; scanf("%d",&N);
        rep(i,1,N) scanf("%d",&a[i]);
        rep(i,1,N){
            int now=1,sum=0,j=i; ans++;
            while(j+1<=N&&(sum+now*(a[j+1]-a[j]))<20)
                sum+=now*(a[j+1]-a[j]),now++,j++;
            i=j;
        }
        printf("%d",ans);
        return 0;
    }
    View Code

    E. Explosion Exploit

    题意:给定N个自己人,M个敌人。以及每个人的血量ai。系统一共发起K次攻击,每次随机选择一个人物进行攻击,被攻击后血量少1,血量为0的不再考虑。问最后敌人都被杀死的概率。 (N,M<=5 ,ai<=6,K<=100)

    思路:因为数据都比较小,我们可以考虑记忆化搜索,显然我们不能开10维数组来模拟,空间不够。  我们需要维护两个集合,分别是自己人的血量和敌人的血量,然后记忆化搜索。 集合我们可以用vector来表示,每次向下搜索前vector可以先排序,这样可以减很多的枝。   我的代码没用数组表示集合,用的是long long。

    因为魔改了几次,所以代码比较丑。

    #include<bits/stdc++.h>
    #define ll long long
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    map<ll,double>mp; int N,M,K;
    int a[13],b[13],sum,FCY; ll P[20];
    int c[13],cnt;
    void Change(ll &x){ //集合内部排序
        ll res=0;
        for(int i=N;i>=1;i--) a[i]=x%10,x/=10;
        for(int i=M;i>=1;i--) b[i]=x%10,x/=10;
        sort(a+1,a+N+1); sort(b+1,b+M+1);
        rep(i,1,M) res=res*10+b[i],c[N+M+1-i]=b[i];
        rep(i,1,N) res=res*10+a[i],c[N+1-i]=a[i];
        cnt=0; rep(i,1,N) if(a[i]) cnt++; rep(i,1,M) if(b[i]) cnt++;
        x=res;
    }
    double dfs(ll Now,int D)
    {
        Change(Now); int num=cnt,d[13];
        rep(i,1,N+M) d[i]=c[i];
        if(mp.find(Now)!=mp.end()) return mp[Now];
        if(Now<FCY) return mp[Now]=1.0;
        if(D==0) return mp[Now]=0.0;
        double res=0;
        rep(i,1,N+M) {
            if(d[i]==0) continue;
            d[i]--; if(d[i]==0) num--;
            res+=dfs(Now-P[i-1],D-1)/(num+(d[i]==0));
            if(d[i]==0) num++; d[i]++;
        } return mp[Now]=res;
    }
    int main()
    {
        scanf("%d%d%d",&N,&M,&K);
        rep(i,1,N) scanf("%d",&a[i]),sum+=a[i];
        rep(i,1,M) scanf("%d",&b[i]),sum+=b[i];
        if(K>=sum) return puts("1.00000000"),0;
        ll Now=0; FCY=1; P[0]=1; cnt=N+M;
        rep(i,1,N+M) P[i]=P[i-1]*10;
        rep(i,1,M) Now=Now*10+b[i],c[N+M+1-i]=b[i];
        rep(i,1,N) Now=Now*10+a[i],FCY*=10,c[N+1-i]=a[i];
        printf("%.8lf
    ",dfs(Now,K));
        return 0;
    }
    View Code

    H .House Lawn

    by 许

    #include<bits/stdc++.h>
    #define db double
    #define ll long long
    using namespace std;
    const int maxn=1e6+6,inf=1e9;
    char str[1005];
    struct node
    {
        char s[65];
        int id,p;
        bool operator<(const node&t)const
        {
            if(p==t.p)return id<t.id;
            return p<t.p;
        }
    }a[105];
    void gao(int cur,int &pri,int &c,int &t,int &r)
    {
        int n=strlen(str),i=0;
        pri=c=t=r=0;
        while(str[i]!=',')i++;
        i++;
        while(str[i]!=',')
        pri=pri*10+str[i++]-'0';i++;
        while(str[i]!=',')
        c=c*10+str[i++]-'0';i++;
        while(str[i]!=',')
        t=t*10+str[i++]-'0';i++;
        while(i<n)
        r=r*10+str[i++]-'0'; 
    }
    int main()
    {
        int e,m,pri,c,t,r,v,n=10080,cnt=0;
        cin>>e>>m;
        getchar();
        for(int i=1;i<=m;i++)
        {
            gets(str);
            gao(i,pri,c,t,r);
            v=n/(t+r)*t*c;
            if(v<e)
            {
                int tmp=n%(t+r);
                db v1=(db(e)-v)/c,v2=tmp-v1;
                if(v1<=(db)t)
                if(v1*r<=v2*t)v=e;
            }
            if(v>=e)
            {
                a[++cnt].p=pri; a[cnt].id=i;
                int len=strlen(str),j=0;
                while(str[j]!=',')
                a[cnt].s[j]=str[j],j++;
                a[cnt].s[j]='';
            }
        }
        sort(a+1,a+1+cnt);
        if(cnt==0)puts("no such mower");
        else
        {
            int i=1;
            while(1)
            {
                printf("%s
    ",a[i++].s);
                if(i>cnt||a[i].p>a[i-1].p)break;    
            }
        }
    }
    View Code

    I .Intergalactic Bidding

    题意:给出N个高精度数,表示N个人对应的数字,满足每个人的数字大于等于前面一个人的两倍,以及S。 输出winners,一个人是winner,当且仅当他存在一个集合里,这个集合是和是S。

    思路:首先挖掘为何有大于等于两倍,我们发现它告诉我们每一个集合表示出来的数都是不同的,而每一个S对应的集合也是唯一的,所以要么没有winner,要么我们可以从大到小贪心地拼凑出S。

    by 罗

    elect Code
    
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll mod=998244353;
    const int maxn=1e6+50;
    const ll inf=0x3f3f3f3f3f3f3f3fLL;
    string s;
    int cmp(string a,string b){
        if(a.length()>b.length())return true;
        else if(a.length()<b.length())return false;
        else return a>=b;
    }
    bool vis[1100];
    struct node{
        string name;
        string money;
    }my[1100];
    bool cmpp(node a,node b){
        if(a.money.size()>b.money.size())return true;
        else if(a.money.size()<b.money.size())return false;
        else return a.money>b.money;
    }
    string sub(string a,string b){
        string ans="";
        reverse(a.begin(),a.end());
        reverse(b.begin(),b.end());
        int len1=a.length(),len2=b.length();
        int pre=0;
        for(int i=0;i<len2;i++){
            int now=a[i]-b[i];
            if(now<0)a[i+1]--,now=10+now;
            ans+=(char)(now+'0');
        }
        for(int i=len2;i<len1;i++){
            int num=a[i]-'0';
            if(num<0){
                num+=10;
                a[i+1]--;
            }
            ans+=(char)(num+'0');
        }
        while(ans.size()>1&&ans.back()=='0')ans.pop_back();
        reverse(ans.begin(),ans.end());
        return ans;
    }
    int main()
    {
        std::ios::sync_with_stdio(false);
        std::cin.tie(0);
        std::cout.tie(0);
        int n;
        cin>>n;
        cin>>s;
        for(int i=1;i<=n;i++){
            cin>>my[i].name>>my[i].money;
        }
        int num=0;
        sort(my+1,my+1+n,cmpp);
        for(int i=1;i<=n;i++){
            if(cmp(s,my[i].money)){
                s=sub(s,my[i].money);
                vis[i]=1;
                num++;
            }
        }
        if(s=="0"){
            cout<<num<<endl;
            for(int i=1;i<=n;i++){
                if(vis[i])cout<<my[i].name<<endl;
            }
        }
        else{
            cout<<"0"<<endl;
        }
        return 0;
    }
    View Code

    J .Jumbled String

    题意: 给你00,01,10,11的数量a,b,c,d。 让你根据信息还原一个字符串 。

    思路:由00和11的数量,我们可以得到字符串中0和1的数量x和y,然后取凑即可, 注意00数量为0时,x可能为0,也可能为1,其它情况下,x唯一; y同理。

    假设得到了x,y。 我们可以试着构造一个形如11111...0001000....1111的串,即中间可以夹杂一个1。

    #include<bits/stdc++.h>
    #define ll long long
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=3010;
    const int Mod=1e9+7;
    map<int,int>mp;
    bool check(int A,int D,int B,int C)// 0,1
    {
        if(1LL*A*D!=1LL*B+C) return false;
        if(A==0&&B==0&&C==0){
            rep(i,1,D) putchar('1'); return true;
        }
        if(D==0&&B==0&&C==0){
            rep(i,1,A) putchar('0'); return true;
        }
        int num=B/A,rem=B%A;
        rep(i,1,D-num-(rem!=0)) putchar('1');
        rep(i,1,A) {
            putchar('0');
            if(rem==i) putchar('1');
        }
        rep(i,1,num) putchar('1');
        return true;
    }
    int main()
    {
        int A,B,C,D;
        rep(i,1,44721){
           int tmp;
           if(i&1) tmp=(i-1)/2*i;
           else tmp=i/2*(i-1);
           mp[tmp]=i;
        }
        scanf("%d%d%d%d",&A,&B,&C,&D);
        if(mp[A]==0) return puts("impossible"),0;
        if(mp[D]==0) return puts("impossible"),0;
        if(check(mp[A],mp[D],B,C)) return 0;
        if(A==0&&check(0,mp[D],B,C)) return 0;
        if(D==0&&check(mp[A],0,B,C)) return 0;
        if(A==0&&D==0&&check(0,0,B,C)) return 0;
        puts("impossible");
        return 0;
    }
    View Code

     

    K .King's Colors

    题意:给你N,K,一棵大小为N的树,求刚好染K种色,而且相邻边颜色不同的方案数。

    思路:一眼容斥题,我们用F(x)表示颜色大于等于x的方案数,则ans=F(K)*C(K,K) -F(K-1)*C(K,K-1)+F(K-2)*C(K,K-2)...

    而这又是一棵树,所以我们从上到下染色,每个点只要和父亲颜色不同即可。 所以F(x)=x*(x-1)^(N-1);

    #include<bits/stdc++.h>
    #define ll long long
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=3010;
    const int Mod=1e9+7;
    int C[maxn][maxn],N,K,ans;
    int qpow(int a,int x)
    {
        int res=1; while(x){
            if(x&1) res=(ll)res*a%Mod;
            a=(ll)a*a%Mod; x>>=1;
        } return res;
    }
    int main()
    {
        rep(i,0,2500) C[i][0]=C[i][i]=1;
        rep(i,1,2500)
          rep(j,1,i) C[i][j]=(C[i-1][j-1]+C[i-1][j])%Mod;
         scanf("%d%d",&N,&K);
        rep(i,2,N){
            int u; scanf("%d",&u);
        }
        for(int i=K;i>=2;i--){
            if((K-i)%2==0){
                (ans+=(ll)i*qpow(i-1,N-1)%Mod*C[K][i]%Mod)%=Mod;
            }
            else {
                ans=((ans-(ll)i*qpow(i-1,N-1)%Mod*C[K][i]%Mod)%Mod+Mod)%Mod;
            }
        }
        printf("%d
    ",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    Unity Find 使用规则
    Unity UGUI
    Unity UGUI
    Unity UGUI
    Unity UGUI
    机器学习:支持向量机识别手写英文字母 SMO算法实现二元分类器
    机器学习:朴素贝叶斯分类器实现二分类(伯努利型) 代码+项目实战
    机器学习:基于CART算法的决策树——分类树与回归树
    机器学习:决策树——分类树 ID3算法 代码+案例
    JAVA
  • 原文地址:https://www.cnblogs.com/hua-dong/p/10346375.html
Copyright © 2020-2023  润新知