• Codeforces1332 题解


    前言

    出题人:用心出题目, 用脚造数据。 C pretest竟然没有极限数据导致我fst了,好气啊。

    正文

    AB就不讲了。

    C. K-Complete Word

    考虑回文位和 (i + k) 位和 (i) 位要相同,把所有要求相同的一起找出来全部变成最多的那个就好了。

    #include<bits/stdc++.h>
     
    using namespace std;
     
    #define N 200005
     
    int T, n, k, cnt[27]; 
     
    string s;
     
    bool vis[N];
     
    int main()
    {
    	ios::sync_with_stdio(false);
    	cin >> T;
    	while(T--)
    	{
    		int ans = 0;
    		cin >> n >> k;
    		for(int i = 0; i <= n; i++) vis[i] = 0;
    		cin >> s;
    		for(int i = 0; i < n; i++)
    		{
    			if(vis[i]) continue;
    			memset(cnt, 0, sizeof(cnt));
    			int j = i, num = 0;
    			while(j < n) 
    			{
    				if(!vis[j]) cnt[s[j] - 'a']++, num++;
    				vis[j] = 1;
    				int x = n - j - 1;
    				if(!vis[x]) cnt[s[x] - 'a']++, num++;
    				vis[x] = 1;
    				j += k;
    			}
    			int tmp = 0;
    			for(int i = 0; i < 26; i++) tmp = max(tmp, cnt[i]);
    			ans += num - tmp;
    		}
    		printf("%d
    ", ans);
    	}
    	return 0;
    }
    

    D. Walk on Matrix

    考虑构造,让Bob答案为0,最佳答案为 (k) 即可。

    #include<bits/stdc++.h>
     
    using namespace std;
     
    int k, limit = 1, l = 0, all = (1 << 18) - 1, x = (1 << 17);
     
    int main()
    {
    	cin >> k;
    	cout << 3 << ' ' << 3 << endl;
    	cout << all << ' ' << all << ' ' << k << endl;
    	cout << all << ' ' << x << ' ' << x + k << endl;
    	cout << k << ' ' << x + k << ' ' << k << endl;
    	return 0;
    }
    

    E. Height All the Same

    首先通过2操作我们可以发现直接把所有数 (mod 2) 一定是可以的。那么我们现在只需要考虑只有 (0、1) 的矩阵

    Case1. (n & 1) && (m & 1)
    (sum) 奇偶讨论一下可以发现无论怎样一定有解。

    Case2. !((n & 1) && (m & 1)) && (sum & 1)

    由于操作不能改变 (sum) 的奇偶性,那么可以发现无解。

    Case3. !(sum & 1)

    此时一定可以通过一些1和2操作来同时改变两个1的值。所以此时有解。
    我们定义(x, y) 分别为 (L, R) 中偶数,奇数的数量。我们要求

    [sum_{i = 0}^{frac{nm}{2}}{x^{nm - 2i} imes y^{2i} imes C_{nm}^{2i}} \ (x + y)^{nm} = sum_{i = 0}^{frac{nm}{2}}{x^{nm - 2i} imes y^{2i} imes C_{nm}^{2i}} + sum_{i = 1}^{frac{nm}{2}}{x^{nm - 2i - 1} imes y^{2i - 1} imes C _{nm}^{2i - 1}} \ (y - x)^{nm} = sum_{i = 0}^{frac{nm}{2}}{x^{nm - 2i} imes y^{2i} imes C_{nm}^{2i}} - sum_{i = 1}^{frac{nm}{2}}{x^{nm - 2i - 1} imes y^{2i - 1} imes C _{nm}^{2i - 1}} ]

    所以快速幂一下就出来了

    #include<bits/stdc++.h>
     
    using namespace std;
     
    typedef long long ll;
    #define N 250005
    const int mod = 998244353;
    #define add(x, y) (x + y >= mod ? x + y - mod : x + y)
    #define dec(x, y) (x < y ? x - y + mod : x - y)
     
    ll Pow(ll x, ll k)
    {
    	ll ans = 1, base = x;
    	while(k)
    	{
    		if(k & 1) ans = 1ll * ans * base % mod;
    		base = 1ll * base * base % mod;
    		k >>= 1;
    	}
    	return ans;
    }
     
    ll n, m, L, R;
     
    int main()
    {
    	cin >> n >> m >> L >> R;
    	if((n % 2) && (m % 2))
    	{
    		printf("%lld
    ", Pow(R - L + 1, n * m));
    	}
    	else
    	{
    		ll x = 0, y = 0;
    		if(L & 1) y++, L++;
    		if((R & 1) && L <= R - 1) y++, R--;
    		if(L <= R)
    		{
    			x += (R - L) / 2 + 1;
    			y += R - L + 1 - x;
    		}
    		cout << (Pow(2, mod - 2) * (Pow(x + y, n * m) + Pow(y - x, n * m)) % mod + mod) % mod << endl;
    	}
    	return 0;
    }
    

    F. Independent Set

    首先发现是个树形dp(我读题读了好久,嘤文太差/kel)

    (f[i][0/1/2]) 表示i作为根节点时,它被(在子图不在独立集)/(在子图在独立集)/(不在子图)的方案数。

    在转移时,对于每个儿子节点,考虑根节点到这个儿子的这条边被不被选进去。接下来是方程。

    [设 sum = f[v][0] + f[v][1] + f[v][2] \ f[x][0] = (f[x][0] + f[x][2]) imes (sum + f[v][2]) + f[x][0] imes sum \ f[x][1] = (f[x][1] + f[x][2]) imes (f[v][0] + f[v][2]) + f[x][1] imes sum \ f[x][2] = f[x][2] imes sum \ 对于每个儿子按此顺序转移。 ]

    对于 (f[x][0]) 处的 (sum + f[v][2]) 的意思:此时v并不确定有没有被选进去,当我做v的时候,它和儿子的边可以全部断开,然后在这里连上一条边被选进来,此时他可以有在或不在子图里两种状态,所以要乘2, 最好自己画个图就理解了。

    #include<bits/stdc++.h>
     
    using namespace std;
     
    #define N 300005
    const int mod = 998244353;
    #define add(x, y) (x + y >= mod ? x + y - mod : x + y)
    #define dec(x, y) (x < y ? x - y + mod : x - y)
     
    int n, head[N], nxt[N << 1], to[N << 1], cnt = 0, f[N][3], num = 0;
     
    void add_e(int x, int y)
    {
    	cnt++;
    	to[cnt] = y;
    	nxt[cnt] = head[x];
    	head[x] = cnt;
    }
     
    void dfs(int x, int fa)
    {
    	f[x][2] = 1;
    	for(int p = head[x]; p; p = nxt[p])
    	{
    		int v = to[p];
    		if(v == fa) continue;
    		dfs(v, x);
    		int sum = add(f[v][0], add(f[v][1], f[v][2]));
    		f[x][0] = add(1ll * f[x][0] * sum % mod, 1ll * add(f[x][0], f[x][2]) * add(sum, f[v][2]) % mod);
    		f[x][1] = add(1ll * f[x][1] * sum % mod, 1ll * add(f[x][1], f[x][2]) * add(f[v][0], f[v][2]) % mod);
    		f[x][2] = 1ll * f[x][2] * sum % mod;
    	}
    }
     
    int main()
    {
    	scanf("%d", &n);
    	for(int i = 1; i <= n - 1; i++)
    	{
    		int x, y;
    		scanf("%d%d", &x, &y);
    		add_e(x, y), add_e(y, x);
    	}
    	dfs(1, 0);
    	printf("%d
    ", dec(add(add(f[1][0],  f[1][1]), f[1][2]), 1));
    	return 0;
    }
    
  • 相关阅读:
    TCP/IP笔记 一.综述
    Makefile的规则
    u盘安装ubuntu10.04 server.txt
    浅谈数据库技术,磁盘冗余阵列,IP分配,ECC内存,ADO,DAO,JDBC
    cocos2d-js 热更新具体解释(一)
    C#一个托付的样例
    JAVA学习之 异常处理机制
    阿里巴巴校招内推简历筛选方案
    《凑硬币》 动态规划算法入门
    android 读取xml
  • 原文地址:https://www.cnblogs.com/LJB00131/p/12618498.html
Copyright © 2020-2023  润新知