• 第八届“图灵杯”NEUQ-ACM程序设计竞赛个人赛(同步赛)8题(BCDHIJKL)


    https://ac.nowcoder.com/acm/contest/11746
    好久没写过代码了,思维能力下降,爬了

    A. 切蛋糕

    待补

    B. 小宝的幸运数组

    套路题,初始化tmp为0,从头遍历一遍数组,用tmp加上当前a[i]再对k取模,如果有两个位置得到的模数一样,说明这一段的和就是k的倍数。因为要求最长的子列,注意到k的范围只有1e5,因此只需要用一个桶记录某个得到的模数最开始出现的位置即可。

    #include <iostream>
    #define int long long
    using namespace std;
    int n, k, a[200005];
    int pre[200005] = {-1};
    signed main()
    {
        int t;
        cin >> t;
        while(t--)
        {
            cin >> n >> k;
            long long tot = 0;
            for (int i = 0; i <= 100005; i++)
                pre[i] = -1;
            for (int i = 1; i <= n; i++)
            {
                cin >> a[i];
                tot += a[i];
            }
            if(n == 1)
            {
                if(a[1] == k) cout << 1 << endl;
                else cout << -1 << endl;
                continue;
            }
            if(k == 1|| tot % k == 0)
            {
                cout << n << endl;
                continue;
            }
            int tmp = 0;
            int ans = -1;
            a[0] = 0;
            for (int i = 0; i <= n; i++)
            {
                tmp = (tmp + a[i]) % k;
                //cout << tmp << ' ';
                if (pre[tmp] == -1)
                    pre[tmp] = i;
                else
                {
                   //cout << tmp << ' ' << pre[tmp] << endl;
                    ans = max(ans, i - pre[tmp]);
             
                }
            }
            //cout << endl;
    
            cout << ans << endl;
        }
        return 0;
    }
    

    C. 上进的凡凡

    dp水题。dp[i]代表以a[i]结尾的非降连续子数组的个数,有转移方程: dp[i] += (a[i] >= a[i - 1]) ? dp[i - 1] : 0;

    统计答案即可。

    #include <iostream>
    using namespace std;
    long long n, a[100005], dp[100005];
    int main()
    {
        cin >> n;
        for (int i = 1; i <= n; i++)
        {
            cin >> a[i];
            dp[i] = 1;
        }
        long long ans = 0;
        for (int i = 1; i <= n; i++)
        {
            if(a[i] >= a[i - 1])
                dp[i] += dp[i - 1];
            ans += dp[i];
        }
        cout << ans;
        return 0;
    }
    

    D. Seek the Joker I

    巴什博弈(比赛的时候脑补的)。先手最优策略是等后手拿x张以后选择拿k + 1 - x张,这样相当于拿了有限组的k + 1张,用n % (k + 1) 得到剩下的,这时候先手只要在第一次拿的时候拿走n % (k + 1) - 1张,这样最终会留下一张小丑给后手。如果没法这样拿的话说明先手必败。

    #include <iostream>
    using namespace std;
    int main()
    {
        int t;
        cin >> t;
        while(t--)
        {
            int n, k;
            cin >> n >> k;
            int tmp = n % (k + 1);
            if(tmp > 1 || tmp == 0)
                cout << "yo xi no forever!" << endl;
            else
                cout << "ma la se mi no.1!" << endl;
        }
        return 0;
    }
    

    E. Seek the Joker II

    威佐夫博弈,不会QAQ

    F. 成绩查询ing

    据说可以map瞎搞

    G. 贪吃的派蒙

    H. 数羊

    估计是改编自HDU1165。直接暴力不可取,但注意到m范围只有0,1,2,因此考虑求出来一部分公示缩减递归的规模,比如可以求出来m==1的情况,剩下的再递归就可以了。答案把所有公式都写出来了也可以。

    #include <iostream>
    #define p 998244353
    using namespace std;
    long long n, m;
    long long A(long long n, long long m)
    {
        if(n == 1 && m == 0)
            return 2;
        if(n == 0)
            return 1;
        if(m == 0)
            return (n % p + 2) % p;
        if(n == 1 && m == 1)
            return 2;
        if(m == 1)
            return 2 * n;
        return A(A(n - 1, m), m - 1) % p;
    }
    int main()
    {
        int t;
        cin >> t;
        while(t--)
        {
            cin >> n >> m;
            cout << A(n, m) % p << endl;
        }
        return 0;
    }
    

    I. 买花

    可以随便瞎搞,我选择求一个前缀和然后枚举子数组判断和能否整除n。

    #include <iostream>
    #define int long long
    using namespace std;
    int a[105], sum[105];
    signed main()
    {
    	//freopen("data.txt", "r", stdin);
    	a[1] = 1;
    	sum[1] = 1;
    	for(int i = 2; i <= 20; i++)
    	{
    		a[i] = a[i - 1] * 2;
    		sum[i] = sum[i - 1] + a[i];
    	}
    	int t;
    	cin >> t;
    	while(t--)
    	{
    		int n;
    		cin >> n;
    		bool flag = 0;
    		for(int i = 1; i <= 15; i++)
    		{
    			for(int j = i + 1; j <= 15; j++)
    			{
    				int s = sum[j] - sum[i - 1];
    				if(n % s == 0) 
    				{
    					flag = 1;
    					break;
    				}
    			}
    		}
    		if(flag) cout << "YE5" << endl;
    		else cout << "N0" << endl;
    	}
    	return 0;
    }
    

    J. 这是一道简单的模拟

    题目说的没错。开二维数组写即可。

    #include <iostream>
    #include <vector>
    #define N 305
    #define M 10005
    using namespace std;
    int n, m, k;
    // k, head[N], ver[2 * M], edge[2 * M], Next[2 * M], tot = 0;
    // void add(int x, int y, int z)
    // {
    //     ver[++tot] = y, edge[tot] = z, Next[tot] = head[x], head[x] = tot;
    // }
    int mmap[305][305] = {0};
    int main()
    {
        cin >> n >> m;
        for (int i = 1; i <= m; i++)
        {
            int x, y, z;
            cin >> x >> y >> z;
            //add(x, y, z);
            //add(y, x, z);
            mmap[x][y] = mmap[y][x] = z;
        }
        cin >> k;
        long long cost = 1e15;
        for (int i = 1; i <= k; i++)
        {
            int num;
            cin >> num;
            vector<int> v;
            v.push_back(0);
            long long cc = 0;
            bool flag = 1, vis[305] = { 0 };
            for (int i = 1; i <= num; i++)
            {
                int p;
                cin >> p;
                v.push_back(p);
            }
            v.push_back(0);
            for (int i = 1; i < v.size(); i++)
            {
                vis[v[i]] = 1;
                if (!mmap[v[i]][v[i - 1]]) 
                {
                    flag = 0;
                    break;
                }
                cc += 1ll * mmap[v[i]][v[i - 1]];
            }
            for (int i = 1; i <= n; i++) 
            {
                if(!vis[i])
                {
                    flag = 0;
                    break;
                }
            }
            if(flag)
                cost = min(cost, cc);
        }
        if(cost != 1e15) cout << cost;
        else
            cout << -1;
        return 0;
    }
    

    K. 黑洞密码

    模拟即可,注意循环后移和平时不同,由于最多往后移动九次,因此按照下述代码搞蛮方便的。

    #include <iostream>
    #include <vector>
    using namespace std;
    string s1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZbcdefghijklmn";
    string s2 = "abcdefghijklmnopqrstuvwxyzBCDEFGHIJKLMN";    
    char v1[400];
    int v2[400];
    char ans[400];
    int main()
    {
        //freopen("data.txt", "r", stdin);
        string s;
        cin >> s;
        int pos1 = 0, pos2 = 0;
        for (int i = 0; i < s.size(); i++)
        {
            if(s[i] >= '0' && s[i] <= '9')
                v2[pos2++] = s[i] - '0';
            else
                v1[pos1++] = s[i];
        }
        
        for (int i = 0; i < 4; i++)
        {
            for (int j = 0; j < 4; j++)
            {
                char tmp = v1[i * 4 + j];
                if (tmp >= 'a' && tmp <= 'z')
                {
                    ans[i * 4 + j] = s2[(int)(tmp - 'a') + v2[i * 4 + j]];
                }
                else
                {
                    ans[i * 4 + j] = s1[(int)(tmp - 'A') + v2[i * 4 + j]];
                }
            }
        }
        for (int i = 0; i < 4; i++)
        {
            for (int j = 0; j < 2; j++)
            {
                swap(ans[i * 4 + j], ans[i * 4 + 3 - j]);
            }
        }
        for(int i = 0; i < 16; i++) cout << ans[i];
    }
    

    L. 建立火车站

    看到最大距离最小想到二分,直接对答案区间进行二分,check的时候判断每一段区间能否用现有的k个停靠站分成最大不超过mid的子区间,能的话更新k同时判断下一个区间,不能的话return false。

    #include <iostream>
    #include <vector>
    #include <algorithm>
    #define int long long
    using namespace std;
    long long n, k, pos[100005];
    vector<long long> v;
    bool check(long long mid)
    {
        long long kk = k;
        for (int i = 0; i < v.size(); i++)
        {
            int num = v[i] / mid;
            if(v[i] % mid != 0)
                num++;
            num--;
            if(kk < num)
            {
                return false;
            }
            kk -= num;
        }
        return true;
    }
    signed main()
    {
        cin >> n >> k;
        for (int i = 1; i <= n; i++)
            cin >> pos[i];
        sort(pos + 1, pos + n + 1);
        for (int i = 2; i <= n; i++)
            v.push_back(pos[i] - pos[i - 1]);
        sort(v.begin(), v.end());
        long long l = 1, r = v[v.size() - 1], mid;
        while(l < r)
        {
            mid = (l + r) >> 1;
            //cout << mid << endl;
            if (check(mid))
                r = mid;
            else
                l = mid + 1;
        }
        cout << l;
        return 0;
    }
    
  • 相关阅读:
    shell 命名管道,进程间通信
    bash shell:重定向标准错误输出
    paramiko socket.error: Int or String expected
    django csrf_token生成
    shell基础知识
    复制vi全部内容到windows ctrl+shift+c
    linux配置bridge (不同网段)
    sdk shell下脚本.soc
    X86服务器BMC基板管理控制器介绍
    linux 开启vnc
  • 原文地址:https://www.cnblogs.com/lipoicyclic/p/14350382.html
Copyright © 2020-2023  润新知