codeforce刷题(六)

1、Necklace Assembly

给一个长度为\(n\)的字符串,从中挑选出一些字符然后按照你想要的顺序排成一个环,这个环顺时针旋转\(k\)次后与原来的环相同,问环的最大长度。

\(1<=n,k<=2000\)

题解

旋转\(k\)次后依然相同,说明这个环的循环节是\(k\)的因数。

由于\(n,k\) 比较小,可以枚举循环节的长度和环的最大长度,复杂度\(O(n^2)\)

int main()
{
    int n, k, t;
    int cnt[40], tot[2005];
    string s;

    cin >> t;
    while(t--) {
        memset(cnt, 0, sizeof(cnt));

        cin >> n >> k >> s;

        _myfor(i, 0, n) cnt[s[i] - 'a']++;

        int ans = 0;
        myfor(i, 1, min(n, k)) if (k % i == 0) {   // 枚举循环节的长度
            for (int le = n; le > 0; le--) if (le % i == 0) {      // 枚举环的最大长度
                int t = le / i, tot = 0;
                _myfor(j, 0, 26) if (cnt[j] >= t) tot += (cnt[j] / t);
                if (tot >= i) {
                    ans = max(ans, le);
                    break;
                }
            }
        }
        
        cout << ans << endl;
    }
    return 0;
}

2、Task On The Board

给一个字符串\(s\),长度为\(m\)的整数序列\(b\),请构造出满足如下条件的字符串\(str\)

  • \(b[i] = \sum_{str[i] < str[j]}|i-j|\)

\(1 <= m <= len(s) <= 50\)

题解

显然,如果\(b[i] = 0\) 说明第 \(i\) 位置的字符在字符串\(str\)中的字典序最大。

所以我们可以不断找出\(b[i]\)\(0\)的位置,然后依次填入相应的字符。

根据已知的\(b[i] = 0\)的位置(原始序列\(b\)),不断减去这些位置上字符的贡献:\(b[j] = b[j] - \sum_{str[j] < str[i]}|i - j|\),就能得到下一轮哪些位置(\(b[some\_{positon}] = 0\))可以填。

倒推

sort(s.begin(), s.end());

int n = s.size();

vector<int> id;
while(true) {
    id.clear();
    // 找b[i] == 0的位置
    myfor(i, 1, m) if (!b[i] && !use[i]) {
    	id.push_back(i);
    	use[i] = 1;
	} 
	if ((int)id.size() <= 0) break;
	// 填入字符
	char tp;
	for (int i = n - 1; i >= 0; i--) {
		if (cnt[s[i] - 'a'] >= (int)id.size()) {
			tp = s[i];
			cnt[tp - 'a'] = 0;
			break;
		}
		else cnt[s[i] - 'a'] = 0;
	}
	// 减去上一轮那些位置的贡献
	for (auto i: id) {
		ans[i] = tp;
		myfor(j, 1, m) if (b[j]) b[j] -= abs(j - i);
	}
}
myfor(i, 1, m) cout << ans[i];
cout << endl;

3、Two Divisors

\(n\)个数,问每个数(\(a_i\))是否存在两个因数\(d_1\)\(d_2\),使得\(gcd(d_1 + d_2,a_i) = 1\)

\(1<=n<=5*10^5,2<=a_i<=1*10^7\)

题解

已知,任意一个数都可以写成几个质因数的乘积,比如\(8 = 2^3,6 = 2 * 3​。\)

那么将这些质因数分成两个不相交的集合\(s_1\)\(s_2\),令\(d_1= s1\)中所有数的乘积,\(d_2\)同理,

\(gcd(d_1 + d_2, a_i) = 1\) ,所以该问题等价于求\(a_i\)的两个不同的质因数。

最好用线性筛,在筛的同时求出每个合数的最小质因数。

/*
time:1800ms
*/
void Inite() {
    prime[1] = 1;
    for (int i = 2; i * i <= 10000009; i++) if (!prime[i]) {
        p.push_back(i);
        for (int j = i + i; j < N; j += i) prime[j] = 1;
    }
}

int main()
{
    Inite();
    
    cin >> n;
    myfor(i, 1, n) cin >> a[i];

    vector<pair<int, int> > ans;

    myfor(i, 1, n) {
        int tp = a[i];
        bool flag = false;
        for (auto x: p) if (a[i] % x == 0) {
            while(a[i] % x == 0) a[i] /= x;
            if (a[i] != 1) ans.push_back(make_pair(tp / a[i], a[i]));
            else ans.push_back(make_pair(-1, -1));
            flag = true;
            break;
        }
        if (!flag) ans.push_back(make_pair(-1, -1));
    }

    for (auto &x: ans) cout << x.first << " ";
    cout << endl;
    for (auto &x: ans) cout << x.second << " ";
    cout << endl;

    return 0;
}

4、Ehab and Prefix MEXs(好题)

给一个长度为\(n\)的序列\(a\),求满足如下条件且长度为\(n\)的序列\(b\):

  • 对于任意一个\(i(1<=i<=n)\)\(MEX(\{b_1,b_2,···,b_i\}) = a_i\)

\(MEX(\{···\})\)是指:不在给定集合的最小非负数,比如\(MEX(\{1,2,3\}) = 0\)\(MEX\{0,1,3\} = 2\)

\(a_i <= a_{i + 1}\)\(0<=a_i<=i\)

题解

构造方法:假设\(a\)中有\(x\)个不同的数(去重后统计)。如果\(a[i] != a[i - 1]\),那么\(b[i] = a[i - 1]\),因为\(b[1],b[2],···,b[i - 1]\)都取不到\(a[i -1]\)。这就填了\(x - 1\)个位置,然后剩下的\(n - x + 1\)个位置从小到大依次填入\(a\)中没有出现的数(\(n + 1 - x\)个),刚好填完。

困难在于怎么处理\(a[i] ==a[i -1]\)的情况

//code_source: https://blog.csdn.net/qq_45458915/article/details/106822285

5、Game On Leaves

张三和李四在玩游戏:给一颗有\(n\)个节点的无根树,和特定的节点\(x\)。每轮的玩家选定一个\(degree <= 1\)的节点并将其移除,同时删除以该节点为端点的所有边。谁先移除节点\(x\),则其成为赢家。在游戏过程中,他们都采取了最优的策略。问最后谁赢?(张三先手)

题解

Select any leaf node in the tree and remove it together with any edge which has this node as one of its endpoints. A leaf node is a node with degree less than or equal to 1.

无根树的叶子节点的度怎么等于0? 估计是\(n\)可能为1吧,费解

两个人的最优策略是:优先删除其他无关的节点,尽量将\(x\)留在最后。又因为每次只删除叶子节点,所以判断一下\(n - 1\)的奇偶性就行。

posted @ 2020-07-08 13:15  天之道,利而不害  阅读(156)  评论(0编辑  收藏  举报