• 第十六届北京师范大学程序设计竞赛决赛(网络同步赛)


    题目链接  第十六届北京师范大学程序设计竞赛决赛

    一句话总结:迟到选手抢到FB之后进入梦游模式最后因为忘加反向边绝杀失败……

    好吧其实还是自己太弱

    下面进入正题

    Problem A

    签到题(读题是一件非常有趣事情)

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define rep(i, a, b)	for (int i(a); i <= (b); ++i)
    #define dec(i, a, b)	for (int i(a); i >= (b); --i)
    #define MP		make_pair
    #define fi		first
    #define se		second
    
    
    typedef long long LL;
    
    
    int main(){
    
    	int T; string s;
    	scanf("%d", &T);
    
    	while (T--){
    		int n;
    		scanf("%d", &n);
    		int fg = 1;
    		rep(i, 1, n){
    			cin >> s;
    			if (s != "PERFECT") fg = 0;
    		}
    		puts(fg ? "MILLION Master" : "NAIVE Noob");
    	}
    
    
    	return 0;
    }
    

     

    Problem B

    设读进来的那个序列为$b_{i}$

    要还原出的那个序列答案为$a_{i}$

    我们求出$a_{i}$对$b_{i}$每一项的贡献就可以了。

    这个过程实现起来不难。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define rep(i, a, b)	for (int i(a); i <= (b); ++i)
    #define dec(i, a, b)	for (int i(a); i >= (b); --i)
    
    typedef long long LL;
    
    const LL mod = 1e9 + 7;
    const int N  = 1e3 + 10;
    
    int T;
    int n;
    LL  a[N], b[N], c[N];
    LL  k;
    
    inline LL Pow(LL a, LL b, LL mod){
            LL ret(1);
            for (; b; b >>= 1, (a *= a) %= mod) if (b & 1) (ret *= a) %= mod;
            return ret;
    }
    
    void pre(){
    	int cnt = 0;
    	c[++cnt] = 1;
    
    	LL now = 1;
    	rep(i, 1, n - 1){
    		now = now * (k + i - 1) % mod;
    		now = now * Pow((LL)i, mod - 2, mod) % mod;
    		c[++cnt] = now;
    	}
    }
    
    int main(){
    
    	scanf("%d", &T);
    	while (T--){
    		scanf("%d%lld", &n, &k);
    		memset(c, 0, sizeof c);
    		pre();
    
    		rep(i, 1, n) scanf("%lld", b + i);
    		a[1] = b[1];
    		rep(i, 1, n){
    			int cnt = 0;
    			rep(j, i, n){
    				++cnt;
    				b[j] -= (c[cnt] * a[i] % mod);
    				b[j] += mod;
    				b[j] %= mod;
    			}
    
    			a[i + 1] = b[i + 1];
    		}
    
    		rep(i, 1, n - 1) printf("%lld ", a[i]);
    		printf("%lld
    ", a[n]);
    	}
    
    
    	return 0;
    }
    

      

     

    Problem C

    打表之后找规律

    #include<bits/stdc++.h>
    
    using namespace std;
    
    int T;
    int n;
    
    int main(){
    
    	cin >> T;
    	while (T--){
    		cin >> n;
    		cout << fixed << setprecision(10) << (n * n - 1) / 3.0 << endl;
    	}
    	return 0;
    }

     

    Problem D

    这个DP转移

    每个点有两种转移的方向,每个方向取最近的那个点就好了。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define rep(i, a, b)	for (int i(a); i <= (b); ++i)
    #define dec(i, a, b)	for (int i(a); i >= (b); --i)
    #define MP		make_pair
    #define fi		first
    #define se		second
    
    
    typedef long long LL;
    
    const int N = 1e5 + 10;
    
    int T;
    int n, m, k;
    LL a[N], b[N], c[N], f[N], g[N], h[N];
    map <LL, LL> mp;
    set <LL> s;
    
    int main(){
    
    	scanf("%d", &T);
    	while (T--){
    		scanf("%d%d%d", &n, &m, &k);
    		rep(i, 1, n) scanf("%lld", a + i);
    		rep(i, 1, m) scanf("%lld", b + i);
    		rep(i, 1, k) scanf("%lld", c + i);
    
    		rep(i, 1, n) f[i] = 1;
    		rep(i, 1, m) g[i] = 1e15;
    
    		mp.clear();
    		rep(i, 1, n) mp[a[i]] = f[i];
    		mp[1e18] = 1e18, mp[-1e18] = 1e18;
    
    		s.clear();
    
    		rep(i, 1, n) s.insert(a[i]);
    		s.insert(1e18);
    		s.insert(-1e18);
    
    		rep(i, 1, m){
    			LL xx = b[i];
    			auto it = s.lower_bound(xx);
    			g[i] = min(g[i], mp[*it] + abs((*it) - xx) + 1);
    			--it;
    			g[i] = min(g[i], mp[*it] + abs((*it) - xx) + 1);
    		}
    
    		rep(i, 1, k) h[i] = 1e15;
    		mp.clear();
    		rep(i, 1, m) mp[b[i]] = g[i];
    		mp[1e18] = 1e18, mp[-1e18] = 1e18;
    
    
    		s.clear();
    		rep(i, 1, m) s.insert(b[i]);
    		s.insert(1e18);
    		s.insert(-1e18);
    
    		rep(i, 1, k){
    			LL xx = c[i];
    			auto it = s.lower_bound(xx);
    			h[i] = min(h[i], mp[*it] + abs((*it) - xx) + 1);
    			--it;
    			h[i] = min(h[i], mp[*it] + abs((*it) - xx) + 1);
    		}
    
    		LL ans = 1e18;
    		rep(i, 1, k) ans = min(ans, h[i]);
    		printf("%lld
    ", ans);
    	}
    
    	return 0;
    }
    

     

     

    Problem E

    考虑到长度为$k$的子序列个数不超过$10^{5}$,那么直接暴力,搜索深度不超过$9$。

    注意:$k$比较大的时候考虑反面即可。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define rep(i, a, b)	for (int i(a); i <= (b); ++i)
    #define dec(i, a, b)	for (int i(a); i >= (b); --i)
    #define MP		make_pair
    #define fi		first
    #define se		second
    
    
    typedef long long LL;
    
    const int N = 1e5 + 10;
    
    int T;
    int n, k;
    int z;
    int c[N];
    LL  a[N];
    LL  ans;
    
    void check(LL x){
    	LL vv = x * x;
    	ans ^= vv;
    }
    
    void dfs(int x, LL now){
    	if (x > k){
    		check(now);
    		return;
    	}
    
    	else{
    		rep(i, z, n){
    			int la = z;
    			z = i + 1;
    			dfs(x + 1, now + a[i]);
    			z = la;
    		}
    	}
    }
    
    void dfs2(int x, LL now){
    	if (x > k){
    		check(now);
    		return;
    	}
    
    	else{
    		rep(i, z, n){
    			int la = z;
    			z = i + 1;
    			dfs2(x + 1, now - a[i]);
    			z = la;
    		}
    	}
    }
    
    
    int main(){
    
    	scanf("%d", &T);
    	while (T--){
    		scanf("%d%d", &n, &k);
    		LL sum = 0;
    		rep(i, 1, n) scanf("%lld", a + i), sum += a[i];
    		z = 1;
    		ans = 0;
    		if (k > n - k){
    			k = n - k;
    			dfs2(1, sum);
    		}
    		else{
    			dfs(1, 0);
    		}
    		printf("%lld
    ", ans);
    	}
    
    
    	return 0;
    }
    

     

     

    Problem F

    显然答案是单调的。

    二分答案,把那些符合条件的汤圆一个个加入队列,然后BFS,到最后如果所有汤圆都被删除了,那么该答案可行。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define rep(i, a, b)	for (int i(a); i <= (b); ++i)
    #define dec(i, a, b)	for (int i(a); i >= (b); --i)
    #define MP		make_pair
    #define fi		first
    #define se		second
    
    
    typedef long long LL;
    typedef pair <int, LL> PII;
    
    const int N = 1e5 + 10;
    
    int T;
    int n, m;
    int vis[N], inq[N];
    LL a[N], bb[N];
    LL l, r;
    vector <PII> v[N];
    
    
    bool check(LL now){
    	queue <int> q;
    	memset(vis, 0, sizeof vis);
    	memset(inq, 0, sizeof inq);
    	rep(i, 1, n) bb[i] = a[i];
    	rep(i, 1, n) if (bb[i] <= now) q.push(i), inq[i] = 1;
    	
    	while (!q.empty()){
    		int x = q.front();
    		vis[x] = 1;
    		q.pop();
    		inq[x] = 0;
    
    		for (auto edge : v[x]){
    			int u = edge.fi;
    			LL  w = edge.se;
    			if (vis[u]) continue;
    			bb[u] -= w;
    			if (bb[u] <= now){
    				if (!inq[u]) q.push(u), inq[u] = 1;
    			}
    		}
    	}
    
    	rep(i, 1, n) if (!vis[i]) return false;
    	return true;
    }
    
    int main(){
    
    	scanf("%d", &T);
    	while (T--){
    		scanf("%d%d", &n, &m);
    		rep(i, 0, n + 1) v[i].clear();
    		rep(i, 0, n + 1) a[i] = 0;
    		rep(i, 1, m){
    			int x, y;
    			LL z;
    			scanf("%d%d%lld", &x, &y, &z);
    			v[x].push_back({y, (LL)z});
    			v[y].push_back({x, (LL)z});
    			a[x] += z;
    			a[y] += z;
    		}
    
    		l = 0, r = 1e14;
    
    		while (l + 1 < r){
    			LL mid = (l + r) / 2ll;
    			if (check(mid)) r = mid;
    			else l = mid + 1;
    		}
    
    		if (check(l)) printf("%lld
    ", l);
    		else printf("%lld
    ", r);
    	}
    
    	return 0;
    }

     

    Problem G

    模拟题,没什么好说的。(我还是WA了好几发)

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define	rep(i, a, b)	for (int i(a); i <= (b); ++i)
    #define	dec(i, a, b)	for (int i(a); i >= (b); --i)
    #define	MP		make_pair
    #define	fi		first
    #define	se		second
    
    typedef long long LL;
    
    char s[24];
    bool ff[24];
    int T;
    
    bool upper(char c){ return c >= 'A' && c <= 'Z'; }
    
    bool check(int n){
    	bool re = 1;
    	bool flag = 0;
    	int cnt = 0;
    	if (!upper(s[0])) s[0] += 'A' - 'a', flag = 1;
    
    	rep(i, 1, n - 1){
    		if (upper(s[i]) && upper(s[i - 1])) re = 0;
    		if (upper(s[i])) cnt++, ff[i] = 1;
    	}
    
    	if (flag) s[0] += 'a' - 'A';
    	return re && (cnt) && !upper(s[n - 1]);
    }
    
    
    int main(){
    
    
    	cin >> T;
    
    	while (T--){
    		scanf("%s", &s);
    		memset(ff, 0, sizeof ff);
    		int n = strlen(s);
    		if (check(n)){
    			rep(i, 0, n - 1){
    				if (ff[i]) putchar('_');
    				if (upper(s[i])) s[i] += 'a' - 'A';
    				putchar(s[i]);
    			}
    			putchar(10);
    		}
    		else puts(s);
    	}
    
    	return 0;
    }
    

    Problem H

    数据结构题,留坑。

    Problem I

    每次交换相邻的两个不一样的元素会使整个序列的逆序对数改变$1$

    那么计算一下逆序对个数就好了。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define rep(i, a, b)	for (int i(a); i <= (b); ++i)
    #define dec(i, a, b)	for (int i(a); i >= (b); --i)
    #define MP		make_pair
    #define fi		first
    #define se		second
    
    
    typedef long long LL;
    
    const int N = 1e6 + 10;
    
    int T;
    int n;
    int a[N];
    char s[N];
    LL  k;
    
    
    int main(){
    
    	scanf("%d", &T);
    	while (T--){
    		scanf("%d%lld", &n, &k);
    		scanf("%s", s + 1);
    
    		rep(i, 1, n) a[i] = (s[i] == 'D');
    		LL cc = 0;
    		rep(i, 1, n) cc += a[i];
    		LL ju = 1ll * cc * (LL)(n - cc);
    		if (ju < k) {
    			puts("-1");
    			continue;
    		}
    
    		LL cnt = 0, ss = 0;
    		rep(i, 1, n){
    			if (a[i] == 0) cnt += ss;
    			ss += a[i];
    		}
    
    		printf("%lld
    ", abs(cnt - k));
    	}
    
    
    	return 0;
    }

    Problem J

    计算几何,留坑。

    Problem K

    留坑。

  • 相关阅读:
    SQLite在php中的接口
    Smarty3——内置函数
    Smarty3——foreach
    Smarty3——复合变量修饰器输
    Smarty3——从配置文件获取的变量
    Smarty3——变量修饰器
    Git命令
    容器云----docker-registry+docker-registry-web(镜像仓库+镜像仓库管理界面)
    容器云----kubernetes-dashboard(kubernetes管理界面)
    容器云----kubernetes+docker-ce
  • 原文地址:https://www.cnblogs.com/cxhscst2/p/8722580.html
Copyright © 2020-2023  润新知