zoukankan      html  css  js  c++  java
  • 第八届“图灵杯”NEUQ-ACM程序设计竞赛个人赛

    A 切蛋糕

    大意:

    现在有一个蛋糕,需要分给k个人,每次操作可以将一个蛋糕分为2份,还可以选择一些蛋糕打包为一份,最后需要打包出k份,使得每一份的蛋糕量为1/k,误差不大于1e-10,全部操作需要在6000步内完成‘

    k保证不大于2e10

    思路:

    直接将所有的蛋糕分为1/1e-10,这样需要的操作数为2e11-1,也就是2047次,然后打包出k份,操作次数不超过2e10,总体不超过2047+1024次,小于6000次

    #include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long LL;
    int const MAXN = 2e5 + 10;
    int n, m, T;
    int two[15];
    void init()
    {
        two[0] = 1;
        for (int i = 1; i < 13; i++)
        {
            two[i] = 2 * two[i - 1];
        }
    }
    
    int main()
    {
        ios_base::sync_with_stdio(false);
        cin.tie(NULL);
        cin >> n;
        init();
        cout << two[11] - 1 + n << endl;    
        int cnt = 0;
        for (int i = 0; i <= 10; i++)
        {
            for (int j = 0; j < two[i]; j++)
            {
                cout << 1 << " " << i << endl;
            }
        }
        double ans = 1.0 / n
        int num = ans / (1.0 / two[11]);
        for (int i = 0; i < n; i++)
        {
            cout << 2 << " " << num;
            for (int j = 0; j < num; j++)
                cout << " " << 11;
            cout << endl;
        }
        return 0;
    }
    

    B 小宝的幸运数组

    大意:

    给出一个长度为n的数组,要求找到一个区间使得区间和为k的倍数,如果有的话输出最长的区间长度,否则输出-1

    思路:

    记录前缀和出现的最早位置,然后相减即可,需要每次都模k,这样保证区间和是k的倍数

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 1e6 + 5;
    typedef long long LL;
    int t, n, r;
    
    LL sum[N], a[N], k;
    map<LL, int> mp;
    int main() {
        cin >> t;
        while (t--) {
            cin >> n >> k;
            mp.clear();
            int res = -1;
            mp[0] = 0;
            for (int i = 1; i <= n; i++) {
                cin >> a[i];
                sum[i] = (sum[i - 1] + a[i] % k) % k;
                if(mp.count(sum[i])){
                    res = max(res, i - mp[sum[i]]);
                }
                else
                    mp[sum[i]] = i;
            }
            cout << res << endl;
        }
        return 0;
    }
    

    C 上进的凡凡

    大意:

    给出长度为n的数组,求出其中不下降子数组的数量

    思路:

    直接扫一遍,如果遇到长度为k的不下降子数组,那么答案应该加上1到k的累加和

    #include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long LL;
    typedef pair<int, int> PII;
    int const N = 2e5 + 10;
    LL n, m, T;
    LL a[N];
    LL jie[N+10];
    void init(){
        jie[0]=jie[1]=1;
        for(int i=2;i<=N;i++){
            jie[i]=jie[i-1]+i;
        }
    }
    int main() {
        cin>>n;
        init();
        for(int i=1;i<=n;i++){
            cin>>a[i];
        }
        LL num=0;
        LL ans=0;
        for(int i=1;i<=n;i++){
            if(a[i]>=a[i-1]) num++;
            else{
                ans+=jie[num];
                num=1;
            }
        }
        ans+=jie[num];
        cout<<ans<<endl;
        return 0;
    }
    

    D Seek the Joker I

    大意:

    一共n个数的堆,从上到下开始取,每次最少取1个,最多取k个,取到最后一个的为输

    先手赢输出yo xi no forever!

    后手赢输出ma la se mi no.1!

    思路:

    巴什博弈裸题

    #include<bits/stdc++.h>
    
    using namespace std;
    
    const int N = 1e6 + 5;
    typedef long long LL;
    int t, n, k;
    int main(){
        cin >> t;
        while(t--){
            cin >> n >> k;
            if (n % (k + 1) == 1) cout << "ma la se mi no.1!" << endl;
            else
                cout << "yo xi no forever!" << endl;
        }
        return 0;
    }
    

    E Seek the Joker II

    大意:

    一个n个数的堆,每次可以从上面取任意个数,或者从下面取任意个数,或者同时从上面和下面取相同多个数,取到原来第x个的为输

    先手赢输出yo xi no forever!

    后手赢输出ma la se mi no.1!

    思路:

    威佐夫博弈裸题

    #include <bits/stdc++.h>
    using namespace std;
    int T;
    int main() {
        int n1,n2,temp, n, x;
        cin >> T;
        while(T--) {
            cin >> n >> x;
            n1 = x - 1, n2 = n - n1 - 1;
            if(n1>n2)  swap(n1,n2);
            temp=floor((n2-n1)*(1+sqrt(5.0))/2.0);
            if(temp==n1) cout<<"ma la se mi no.1!"<<endl;
            else cout<<"yo xi no forever!"<<endl;
        }
        return 0;
    }
    

    F 成绩查询ing

    大意:

    给出n个人的学号、成绩、性别、姓名

    然后是m次查询,如果输入的是成绩,则输出全部的成绩为这个成绩的学生的姓名(按字典序)

    如果查询的是姓名,则输出学生的成绩

    思路:

    直接模拟即可,但是由于n和m比较大,直接查询会超时,但是由于成绩的范围都是1到100,所以可以首先预处理出1到100分的答案,查询的时候直接输出即可

    #include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long LL;
    typedef pair<int, int> PII;
    typedef pair<int, PII> PIII;
    int const N = 1e5 + 10;
    int n, m;
    unordered_map<string,PIII> mp;
    unordered_map<int,set<string>> grade_name;
    string g[N];
    int main() {
        ios_base::sync_with_stdio(false);
        cin.tie(NULL);
        cin >> n;
        for(int i=0;i<n;i++){
            string name;
            int grade,sex,num;
            cin>>name>>grade>>sex>>num;
            PII sex_num={sex,num};
            mp[name]={grade,sex_num};
            grade_name[grade].insert(name);
        }
        for(auto it=grade_name.begin();it!=grade_name.end();it++){
            string s="";
            for(auto i=it->second.begin();i!=it->second.end();i++){
                s=s+(*i);
                s+="
    ";
            }
            g[it->first]=s;
        }
        cin>>m;
        while(m--){
            int t;
            cin>>t;
            if(t==1){
                string name;
                cin>>name;
                //PIII gsn = mp[name];
                cout<<mp[name].first<<" "<<mp[name].second.second<<" "<<mp[name].second.first<<endl;
            }
            else{
                int grade;
                cin>>grade;
                cout<<g[grade];
            }
        }
        
        return 0;
    }
    

    G 贪吃的派蒙

    大意:

    n个人,k份蛋糕。每个人都可以有一个饭量ai,每次轮到一个人的时候,可以取1到ai份蛋糕

    但是这n个人里面有一个贪心者派蒙,他是ai最大的那个人,他一定会取走ai份饭

    所以现在大家想让他刷盘子,也就是最后一个取完蛋糕,问能否使他最后一个取完全部的蛋糕

    注意取完n个人一轮后,如果还有蛋糕,则从第1个人开始取第二轮

    思路:

    直接每一轮模拟即可,从左到右算最小值和最大值,看能否将派蒙包含进里面即可

    #include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long LL;
    LL n, k, t;
    queue<LL> q;
    int main() {
        cin >> t;
        while (t--) {
            cin >> n >> k;
            LL p = 0;
            while(!q.empty()) q.pop();
            for (int i = 0; i < n; i++) {
                LL x;
                cin >> x;
                p = max(p, x);
                q.push(x);
            }
            LL l = 0, r = 0;
            while (1) {
                LL x = q.front();
                q.pop();
    
                if (x == p) {
                    r += x;
                    if (k > l && k <= r) {
                        cout << "YES
    ";
                        break;
                    }
                    if (k <= l) {
                        cout << "NO
    ";
                        break;
                    }
                    l += x;
                } else {
                    l++;
                    r += x;
                }
                q.push(x);
            }
        }
    
        return 0;
    }
    

    H 数羊

    大意:

    给出n和m的值,求A(n,m):

    img

    思路:

    先暴力打表,然后找出规律即可:

    #include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long LL;
    int const MAXN = 2e5 + 10;
    LL n, m, T;
    
    LL qmi(LL a, LL k, LL p) {
        LL res = 1 % p;  // res记录答案, 模上p是为了防止k为0,p为1的特殊情况
        while(k) {  // 只要还有剩下位数
            if (k & 1) res = (LL)res * a % p;  // 判断最后一位是否为1,如果为1就乘上a,模上p, 乘法时可能爆int,所以变成long long
            k >>= 1;  // 右移一位
            a = (LL) a * a % p;  // 当前a等于上一次的a平方,取模,平方时可能爆int,所以变成long long
        }
        return res;
    }
    
    int main() {
        ios_base::sync_with_stdio(false);
        cin.tie(NULL);
        cin >> T;
        while(T--) {
            cin >> n >> m;
            if (n == 1) cout << 2 << endl;
            else if (n == 2) cout << 4 << endl;
            else if (!m) cout << (n + 2) % 998244353 << endl;
            else if (m == 1) cout << n * 2 % 998244353 << endl;
            else cout << 8 * qmi(2, n - 3, 998244353) % 998244353 << endl;
        }
        return 0;
    }
    

    I 买花

    大意:

    n个花,分k天买(k>1,即不能一天全买完),第一天可以买任意朵花,之后每一天买花的数量为前一天的两倍。

    问能否在15天内买够n朵花

    思路:

    设第一天买的花为x个,那么买2天就是买2x+x个,买3天就是买4x+2x+x个...

    所以可以枚举买2到15天的情况,也就是枚举能买到x的倍数,然后看n能否整除某个倍数即可

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 1e6 + 5;
    typedef long long LL;
    int t, n;
    int main() {
        cin >> t;
        while (t--) {
            cin >> n;
            int flag = 0;
            for (int i = 2; i <= 15; i++) {
                if (n % ((1 << i) - 1) == 0) {
                    flag = 1;
                }
            }
            if (flag) cout << "YE5" << endl;
            else
                cout << "N0" << endl;
        }
        return 0;
    }
    

    J 这是一题简单的模拟

    大意:

    从0号点出发到n个城市,然后返回0号点

    现在给出所有的路径,以及k个方案

    问花费最少的方案的花费是多少

    思路:

    直接模拟即可...

    #include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long LL;
    int const MAXN = 3e2 + 10;
    int n, m, k;
    int g[MAXN][MAXN];
    unordered_map<int, int> mp;
    
    int main() {
        ios_base::sync_with_stdio(false);
        cin.tie(NULL);
        cin >> n >> m;
        memset(g, -1, sizeof g);
        for (int i = 1, a, b, c; i <= m; ++i) {
            cin >> a >> b >> c;
            g[a][b] = g[b][a] = c;
        }
        cin >> k;
        LL res = 1e18;
        while(k--) {
            int t;
            cin >> t;
            int curpos = 0;
            LL tmp = 0, flg = 1;
            mp.clear();
            for (int i = 1, p; i <= t; ++i) {
                mp[curpos]++;
                // cout << "cur: " << curpos << endl;
                cin >> p;
                if (g[curpos][p] != -1) {
                    tmp += g[curpos][p];
                    curpos = p;
                }
                else {
                    flg = 0;
                }
            }
            mp[curpos]++;
            if (g[curpos][0]) tmp += g[curpos][0];
            else flg = 0;
            for (int i = 1; i <= n; ++i) if (mp[i] != 1) {
                flg = 0;
                // cout << "ev: " << i << endl;
            }
            if (flg) {
                res = min(res, (LL)tmp);
            }
        }
        if (res != 1e18) cout << res << endl;
        else cout << -1 << endl;
        return 0;
    }
    

    K 黑洞密码

    大意:

    输入一个字符串,然后进行如下操作:

    1.确定讯息的长度为32;

    2.字符串中第(4n+1sim4n+4)的字母和第(4n+1sim4n+4)的数字为一组,共4组;

    3.每组的第1,2,3,4个字符分别往后推每组第1,2,3,4个数字个数 例:如第一个字母为a,第一个数字为3,转换后变为d,'z'之后是'B','Z'之后是'b';

    4.将每组内部字母的顺序颠倒;

    5.将四组字符合并就是最后的讯息。

    思路:

    直接模拟,但是需要注意的是,题目中说了z如果往后移动1位那么会变为B,Z移动一位会变为b,比较坑

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 1e6 + 5;
    typedef long long LL;
    string s;
    char ch[50], num[50];
    string biao =
        "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    int main() {
        cin >> s;
        int cnt1 = 0, cnt2 = 0;
        for (int i = 0; i < s.size(); i++) {
            if (s[i] >= '0' && s[i] <= '9')
                num[++cnt1] = s[i];
            else
                ch[++cnt2] = s[i];
        }
        string res = "";
        for (int i = 0; i <= 3; i++) {
            string temp = "";
            for (int j = 1; j <= 4; j++) {
                char now;
                if(ch[i * 4 + j]>='a'&&ch[i * 4 + j]<='z'){
                    now = biao[ch[i * 4 + j]-'a' + num[i * 4 + j] - '0'];
                    if (now >= 'A' && now <= 'Z') now++;
                }
                else {
                    now = biao[ch[i * 4 + j]-'A'+26 + num[i * 4 + j] - '0'];
                    if (now >= 'a' && now <= 'z') now++;
                }
                temp.push_back(now);
            }
            //cout << temp << endl;
            reverse(temp.begin(),temp.end());
            res = res + temp;
        }
        cout << res << endl;
        return 0;
    }
    

    L 建立火车站

    大意:

    给出n个城市,在这些城市之间可以建立k个车站,问最远的两个车站的最小值是多少(城市也需要看做车站)

    需要注意车站位置必须是整数。

    思路:

    首先将每个区间的距离扔到优先队列里,然后每次都将队头的元素多加一个车站,然后再扔到优先队列里即可

    #include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long LL;
    typedef pair<double, double> PII;
    int const N = 2e5 + 10;
    int n, k;
    double a[N];
    priority_queue<PII, vector<PII>, less<PII> > q;
    int main() {
        cin >> n >> k;
        cin >> a[1];
        for (int i = 2; i <= n; i++) {
            cin >> a[i];
        }
        sort(a + 1, a + 1 + n);
        for (int i = 2; i <= n; i++) {
            q.push({a[i] - a[i - 1], 1});
        }
        while (k--) {
            PII t = q.top();
            double num = t.second;
            double p = t.first * num;
            q.pop();
    
            q.push({p / (num + 1), num + 1});
        }
        cout << ceil(q.top().first) << endl;
        //printf("%lld
    ", ceil(q.top().first));
        return 0;
    }
    
  • 相关阅读:
    Delphi 与 C/C++ 数据类型对照表(最新的tokyo)
    Delphi新语法 For ..In
    NSwag生成客户端调用代码
    微服务
    springcloud
    NET高性能IO
    秒杀场景
    CPU开销sql server 性能调优
    WinDbg调试分析 net站点 CPU100%问题
    全链路实践Spring Cloud 微服务架构
  • 原文地址:https://www.cnblogs.com/dyhaohaoxuexi/p/14351435.html
Copyright © 2011-2022 走看看