• “中国东信杯”广西大学第三届程序设计竞赛


    本来是当做准备校赛前的信心赛打的,结果还是有好几道看了题解才明白.....加油吧~

    A A++++++++++++++++++

    大意:

    对于给出的n个title中,每能组成一对<national,international>,那么竞赛的等级就可以在A的基础上增加一个+,问最后的竞赛等级

    思路:

    取min即可

    #include<iostream>
    using namespace std;
    int main(){
        int t;
        cin>>t;
        while(t--){
            int n;
            cin>>n;
            string s;
            int num1=0,num2=0;
            for(int i=0;i<n;i++){
                cin>>s;
                if(s=="national") num1++;
                if(s=="international") num2++;
            }
            cout<<"A";
            for(int i=0;i<min(num1,num2);i++)
            {
                cout<<"+";
            }
            cout<<endl;
        }
        return 0;
    }
    

    B GDP Carry

    大意:

    给出n个数,Antinomy先手,需要取连续的一段和为奇的数,小西后手,需要取连续的一段和为偶的数,无法继续则判定为输。问在最佳策略下谁会赢

    思路:

    如果n个数的和为奇,那么Antinomy先手直接胜利,如果和为偶,且存在奇数,那么Antinomy可以先取一个奇数,使得剩下的和为奇数(偶数-奇数=奇数),此时小西由于只能选偶数,所以小西必然只能给Antinomy留下奇数,所以又转化为了Antinomy必赢的局面,如果和为偶且不存在奇数,那么小西必赢,因为Antinomy先手没有数可以取。

    #include <bits/stdc++.h>
    using namespace std;
    const int N=1e6+10;
    long long a[N];
    int main(){
            int n;
            cin>>n;
            int f=0;
            long long sum=0;
            for(int i=0;i<n;i++){
                cin>>a[i];
                sum+=a[i];
                if(a[i]%2) f++;
            }
            if(sum%2==0&&f==0) cout<<"XiJam"<<endl;
            else cout<<"Antinomy"<<endl;
        return 0;
    }
    

    C Interpretability

    大意:

    给出n个数字(f_i)代表(2^i)的数量,问由这些数最多能组成多少个三角形

    思路:

    由于都是(2^i),所以只可能是三个相同的数或者两个相同的数加一个较小的数。所以从小到大扫一遍,看将(f_i)拿出一对一对的情况下,和前面(包括自己)单个的边能组成三角形的数量,如果剩下了,就将其作为单个的边记录下来。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long LL;
    typedef pair<int, int> PII;
    int const MAXN = 4e5 + 10;
    LL n, m, T, a[MAXN];
    
    int main() {
        cin >> n;
        for (int i = 1; i <= n; ++i) scanf("%lld", a + i);
        LL pair = 0, single = 0, res = 0;
        LL tmp = 0, minv = 0;
        for (int i = 1; i <= n; ++i) {
            LL pair_cnt = a[i] / 2;
            LL single_cnt = a[i] % 2;
            tmp = pair_cnt;
            single += single_cnt;
            minv = min(pair_cnt, single);
            res += minv;
            LL cnt3 = (pair_cnt - minv) * 2 / 3;
            res += cnt3;
            single -= minv, single += (pair_cnt - minv) * 2 % 3;
        }
        cout << res;
        return 0;
    }
    

    D Batch Normalization 1D

    大意:

    模拟题

    思路:

    大模拟题,不想做了,piao的代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int N = 50;
    const int INF = 0x3f3f3f3f;
    const int mod = 1000000007;
    LL powmod(LL a, LL b) { LL res = 1; a %= mod; assert(b >= 0); for (; b; b >>= 1) { if (b & 1) res = res * a % mod; a = a * a % mod; } return res; }
    
    int n, c, n_batch;
    double eps, momentum;
    double X[N][N];
    double Gamma[N];
    double Beta[N];
    double moving_mean[N];
    double moving_var[N];
    double mu[N];
    double var[N];
    double var_tmp[N][N];
    double X_hat[N][N];
    double out[N][N];
    
    int main() {
    	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    	cin >> n >> c >> n_batch >> eps >> momentum;
    	for (int i = 1; i <= n; i++) {
    		for (int j = 1; j <= c; j++) {
    			cin >> X[i][j];
    		}
    	}
    	for (int i = 1; i <= c; i++) {
    		cin >> Gamma[i];
    	}
    	for (int i = 1; i <= c; i++) {
    		cin >> Beta[i];
    	}
    	for (int i = 1; i <= c; i++) {
    		cin >> moving_mean[i];
    	}
    	for (int i = 1; i <= c; i++) {
    		cin >> moving_var[i];
    	}
    
    	for (int i = 1; i <= c; i++) { //cal mu
    		double sum = 0.0;
    		for (int j = 1; j <= n; j++) {
    			sum += X[j][i]; //order!
    		}
    		mu[i] = sum / n;
    	}
    	//cal var
    	for (int i = 1; i <= n; i++) {
    		for (int j = 1; j <= c; j++){
    			var_tmp[i][j] = pow((X[i][j] - mu[j]), 2);
    		}
    	}
    	for (int i = 1; i <= c; i++) {
    		double sum = 0.0;
    		for (int j = 1; j <= n; j++) {
    			sum += var_tmp[j][i]; //order!
    		}
    		var[i] = sum / n;
    	}
    	while (n_batch--) {
    		for (int i = 1; i <= n; i++) { //cal X_hat
    			for (int j = 1; j <= c; j++) {
    				X_hat[i][j] = (X[i][j] - mu[j]) / sqrt(var[j] + eps);
    			}
    		}
    		for (int i = 1; i <= c; i++) {
    			moving_mean[i] = moving_mean[i] * momentum + (1.0 - momentum) * mu[i];
    		}
    		for (int i = 1; i <= c; i++)  {
    			moving_var[i] = moving_var[i] * momentum + (1.0 - momentum) * var[i];
    		}
    		for (int i = 1; i <= n; i++) { //cal out
    			for (int j = 1; j <= c; j++) {
    				out[i][j] = X_hat[i][j] * Gamma[j] + Beta[j];
    			}
    		}
    	}
    	//last
    	for (int i = 1; i <= n; i++) {
    		for (int j = 1; j <= c; j++) {
    			X_hat[i][j] = (X[i][j] - moving_mean[j]) / sqrt(moving_var[j] + eps);
    		}
    	}
    	for (int i = 1; i <= n; i++) { //cal out
    		for (int j = 1; j <= c; j++) {
    			out[i][j] = X_hat[i][j] * Gamma[j] + Beta[j];
    		}
    	}
    	for (int i = 1; i <= n; i++) {
    		for (int j = 1; j <= c; j++) {
    			cout << out[i][j] << " ";
    		}
    		cout << endl;
    	}
    	return 0;
    }
    

    E Antinomy与黑风海

    大意:

    有向图,从点1出发,每次去其他的点做任务,做完回到1点后才能去下一个点做任务,问做完全部任务需要走多远

    思路:

    很容易看出来前去做任务就是求点1到其他所有点的距离即可,那么怎么求回来的距离呢?直接把每条边反向,重新建一遍图即可

    #include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long LL;
    typedef pair<LL, int> PII;
    int const MAXN = 1e6 + 10, MAXM = 2 * MAXN;
    int n, m, T, h[MAXN], e[MAXM], ne[MAXM], idx, w[MAXM], st[MAXN];
    LL dis[MAXN];
    struct Edge {
        int u, v, c;
    }edge[MAXM];
    
    void add(int a, int b, int c) {
        e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
    }
    
    void dijkstra() {
        memset(dis, 0x3f, sizeof dis);  // 初始化距离为无穷
        priority_queue<PII, vector<PII>, greater<PII> > q;  // 定义一个按照距离从小到大排序的优先队列,第一维:距离,第二维:点
        dis[1] = 0;  // 一开始源点距离为0
        q.push({0, 1});  // 把源点信息放入队列
        while (q.size()) {  // 每个点只出入队列一次
            auto t = q.top();
            q.pop();
            
            LL distance = t.first;
            int ver = t.second;  // 最小距离和相对应的点
            if (st[ver]) continue;  // 这个操作保证每个点只出入队一次,因为队列里面可能会出现{dis1[3], 3}, {dis2[3], 3}的情况,这样保证dis1[3]<dis2[3]时,3号点只进出入队一次
            st[ver] = 1;  // 标记,因为dijkstra的贪心策略保证每个点只需要进出队一次
            
            for (int i = h[ver]; ~i; i = ne[i]) {  // 遍历ver的邻接点
                int j = e[i];
                if (dis[j] > distance + (LL)w[i]) {
                    dis[j] = distance + (LL)w[i];
                    q.push({dis[j], j});  // 这里不需要判断st,因为一旦更新发现更小必须放入队列
                }
            }
        }
    }
    
    int main() {
        memset(h, -1, sizeof h);
        idx = 0;
        cin >> n >> m;
        for (int i = 1; i <= m; ++i) {
            int a, b, c;
            scanf("%d%d%d", &a, &b, &c);
            edge[i] = {a, b, c};
            add(a , b, c);
        }
        dijkstra();
        LL res = 0;
        for (int i = 1; i <= n; ++i) {
            h[i] = -1;
            st[i] = 0;
            if (i != 1) res += dis[i];
        }
        idx = 0;
        for (int i = 1; i <= m; ++i) {
            int a = edge[i].u, b = edge[i].v, c = edge[i].c;
            add(b, a, c);
        }
        dijkstra();
        for (int i = 2; i <= n; ++i) {
            res += dis[i];
        }
        cout << res;
        return 0;
    }
    

    F Antinomy与紫水宫

    大意:

    给出一个树,树上每对距离小于3的节点颜色都不能相同,现在有m种颜色,问有多少种涂色方法

    思路:

    树形dp,首先固定每个节点与其父节点的颜色,那么子节点的颜色数利用组合数可以算出来(A_{m=2}^{子节点数量}),然后向父节点传递即可。注意根节点处因为没有父节点所以要单独写

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 1e5 + 5, mod = 1e9 + 7;
    typedef long long LL;
    int n, m;
    vector<int> mp[N];
    int fact[N], infact[N];
    
    LL qmi(LL a, LL k, LL p) {
        LL res = 1;
        while (k) {
            if (k & 1) res = res * a % p;
            k >>= 1;
            a = a * a % p;
        }
        return res;
    }
    
    // 预处理
    void init() {
        fact[0] = infact[0] = 1;
        for (int i = 1; i < N; ++i) {
            fact[i] = (LL)fact[i - 1] * i % mod;
            infact[i] = (LL)infact[i - 1] * qmi(i, mod - 2, mod) % mod;
        }
    }
    
    int Cnm(int a, int b) {
        return (LL)fact[a] * infact[b] % mod * infact[a - b] % mod;
    }
    
    int res = 1;
    void dfs(int now, int fa) {
        res = (LL)res * Cnm(m - 2, mp[now].size() - 1) % mod *
              fact[mp[now].size() - 1] % mod;  //求Anm;
        for (int i = 0; i < mp[now].size(); i++) {
            int ne = mp[now][i];
            if (ne == fa) continue;
            dfs(ne, now);
        }
    }
    int main() {
        cin >> n >> m;
        init();
        for (int i = 0; i < n - 1; i++) {
            int x, y;
            cin >> x >> y;
            mp[x].push_back(y);
            mp[y].push_back(x);
        }
        res = (LL)res * Cnm(m, mp[1].size() + 1) % mod * fact[mp[1].size() + 1] % mod;
        for (int i = 0; i < mp[1].size(); i++) {
            dfs(mp[1][i], 1);
        }
        cout << res << endl;
        return 0;
    }
    

    G Antinomy与伊修加德

    大意:

    Antinomy想买一些盘子来装拉拉肥,这样可以打包卖出去,每个拉拉肥不能拆开卖。

    每个拉拉肥都有售价,第i个拉拉肥卖出去后的售价是(p_i)金币。

    每个盘子也需要花钱买,第iii个盘子需要花(c_i)金币,能装(b_i)个拉拉肥。

    每个拉拉肥可以卖也可以不卖,但卖就必须要放在一个盘子里。Antinomy的利润就是卖出去的拉拉肥售价总和,减去盘子的花费。

    思路:

    类似01背包的问题,每个盘子取或不取,价值就是拉拉肥的收益-盘子价格,体积就是拉拉肥的个数,注意要先将拉拉肥按照价值排序,因为拉拉肥的体积相同,那么肯定是优先卖价值高的

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 1e6 + 5;
    typedef long long LL;
    int n, m, p[N], b[N], c[N], pre[N],dp[N];
    int main() {
        cin >> n >> m;
        for (int i = 1; i <= n; i++) {
            cin >> p[i];
        }
        sort(p + 1, p + 1 + n, greater<int>());
        for (int i = 1; i <= n; i++) {
            pre[i] = pre[i - 1] + p[i];
        }
        for (int i = 0; i < m; i++) {
            cin >> b[i] >> c[i];
        }
        int res = 0;
        for (int i = 0; i < m;i++){
            for (int j = n; j >= 0;j--){
                if(j>=b[i])
                    dp[j] = max(dp[j], dp[j - b[i]] + pre[j] - pre[j - b[i]] - c[i]);
                else
                    dp[j] = max(dp[j], pre[j] - c[i]);
                res = max(res, dp[j]);
            }
        }
        cout << res << endl;
        return 0;
    }
    

    H Antinomy与太阳神草原

    大意:

    思路:

  • 相关阅读:
    androidstudio配置模拟器路径
    Linux常见命令
    逆向助手使用
    Git服务器回滚到固定版本
    Git使用
    使用本地Gradle版本
    系统模拟器创建
    AndroidStudio设置代理
    关联、参数化、思考时间、检查点、事务的设置方式
    SQL:内连接、左外连接、右外连接、全连接、交叉连接区别
  • 原文地址:https://www.cnblogs.com/dyhaohaoxuexi/p/14179457.html
Copyright © 2020-2023  润新知