zoukankan      html  css  js  c++  java
  • 牛客练习赛20(ABC)

    A. 礼物

    题意:

    我从买奥利奥的事情中想出了一个算法题:假设某个店铺有N种不同类型的1元奥利奥和M种不同类型的2元奥利奥,而且余量无限,我的钱有k元,我想把k元都用来买奥利奥,且可以买同类型的奥利奥,你能帮我算出有多少种购买方式吗?设答案为Z,这个数字也许会很大,所以我们只需要输出Z mod P的值。

    分析:

    计数问题,可以考虑动态规划:每个物品可以选无数次,即无穷背包,注意无穷背包的递推写法。

    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN = 1005;
    int N,M,K,P;
    int d[MAXN];
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--) {
            memset(d,0,sizeof(d));
            scanf("%d%d%d%d",&N,&M,&K,&P);
            d[0] = 1;
            for(int i = 1; i <= N; i++) {
                for(int k = 1; k <= K; k++)
                    d[k] = (d[k] + d[k-1])%P;
            }
            for(int i = 1; i <= M; i++) {
                for(int k = 2; k <= K; k++)
                    d[k] = (d[k] + d[k-2])%P;
            }
            printf("%d
    ",d[K] );
        }
        return 0;
    }
    ​

    B. 麻婆豆腐

    题意:

    “咳咳...请听题!我手上有n枚硬币,第i枚正面朝上的概率是Pi。我现在每个硬币各抛一次,正面朝上看做1,背面朝上看做0,把所有硬币得到的数异或起来决定最后得到的数。问:有多少个子集合使得0和1的概率相等?” 不管音无给了怎样的数,奏都是一分钟不到就算出来了!不愧是前学生会长啊~ 于是他们就去食堂吃麻婆豆腐了,现在,你也来算一下吧。

    分析:

    可以说这个题很惊世骇俗了,当一个硬币的概率是0.5时,它一反转,所得异或值就会改变,而且概率相等,反之,当他的概率不是0.5时,概率必然不等,答案就转化为有多少个集合至少含有一个0.5的硬币,取补集,概率为0.5的硬币是

    
    
    int main() {
        int T; scanf("%d",&T);
        for(int i = 0; i < T; i++) {
            int n;  scanf("%d",&n);
            int cnt = 0;
            double p;
            for(int i = 0; i < n; i++) {
                scanf("%lf",&p);
                if(p==0.5) cnt++;
            }
            cnt = n - cnt;
            long long ans = 1,cnts=1;
            for(int i = 0; i < n; i++)
                ans<<=1;
            for(int i = 0; i < cnt; i++)
                cnts<<=1;
            cout<<ans-cnts<<endl;
    ​
        }
        return 0;
    }

    C. 寻宝

    题意:

    这个迷宫由n个房间组成,编号为0到n - 1,每个房间里都有一颗宝石,房间通过单向通道连接。每个房间里有两个门:一个通向第R个房间(R=(a·v2 + b·v + c) mod n),另一个通向迷宫出口,一旦离开迷宫,便会触发自毁机关,将再也没有机会继续收集宝石。现在,她可以在任何地点进入迷宫,沿隧道移动并收集宝石。

    分析:

    因为每个点,出度均为1,点的数目 ,时间复杂度需要

    那么图里面只有环,和链+环,这样标记遍历即可。

    首先遍历链,发现有环后,从那里再第二次标记,这样,环上每个结点都是环的长度。

    链就相应要短一些。注意,访问的时候,下面的节点已经访问过了。

    #include <bits/stdc++.h>
     
    using namespace std;
     
    long long a,b,c,m;
     
    long long f(long long v) {
        return (a*v*v + b*v + c)%m;
    }
     
    int main()
    {
        //freopen("in.txt","r",stdin);
        int T;
        scanf("%d",&T);
     
        while(T--) {
     
            scanf("%lld%lld%lld%lld",&a,&b,&c,&m);
            vector<long long> L(m,-1);
     
            for(long long i = 0; i < m; i++) {
                if(L[i]>=0) continue;
     
                long long p = i;
                long long plen = 0;
     
                while(L[p]==-1) {
                    L[p] = -2;
                    plen ++;
                    p = f(p);
                }
     
                if(L[p]>0) {
                    plen+=L[p];
                }
     
                long long clen = 0;
                while(L[p]==-2) {
                    L[p] = -3;
                    clen++;
                    p = f(p);
                }
     
                p = i;
                while(L[p]<0) {
                    if(L[p]==-3) L[p] = clen;
                    if(L[p]==-2) L[p] = plen--;
                    p = f(p);
                }
            }
            cout<<*max_element(L.begin(),L.end())<<endl;
        }
        return 0;
    }
  • 相关阅读:
    人生感悟:人与人之间的距离
    9月22日测试题目
    Java自学第五十二天
    Java自学第五十一天
    Java自学第五十天
    Java自学第四十九天
    Java自学第四十八天
    Java自学第四十七天
    Java自学第四十六天
    Java自学第四十五天
  • 原文地址:https://www.cnblogs.com/TreeDream/p/9318472.html
Copyright © 2011-2022 走看看