Educational Codeforces Round 12

Posted zwh_zzz的学习笔记

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Educational Codeforces Round 12相关的知识,希望对你有一定的参考价值。

EDU 12

Educational Codeforces Round 12

A Buses Between Cities

做法:把所有的时间都转换成分钟来考虑这个问题,模拟的情况就很简单了,具体看代码。
代码:

void solve()
	int a, ta;
	int b, tb;
	cin >> a >> ta >> b >> tb;
	string s;
	cin >> s;
	int tim = ((s[0] - \'0\') * 10 + (s[1] - \'0\') ) * 60 + ((s[3] - \'0\') * 10 + s[4] - \'0\');
	int timend = tim + ta;
	int ans = 0;
	for (int now = 300;now < 24 * 60;) 
		if(now <= tim && (now + tb) > tim) 
			ans ++;
		else if(now > tim && now < timend)
			ans++;
		
		now += b;
	
	cout << ans << endl;

B Shopping

做法:直接看样例模拟,具体的意思就是每次排列会交换位置,输出数的位置权值和,鉴定为样例比题目好看懂。
代码:

void solve()
	int n , m , k;
	cin >> n >> m >> k;
	vector<int> a(k + 1);
	vector<int> pos(k + 1);
	for (int i = 1;i <= k;i ++) cin >> a[i];
	for (int i = 1;i <= k;i ++) pos[a[i]] = i;
	int ans = 0;
	for (int i = 1;i <= n;i ++) 
		for (int j = 1;j <= m;j ++) 
			vector<int> tmp;
			tmp.push_back(114514);
			int x;
			cin >> x;
			tmp.push_back(x);
			for (int q = 1;q <= k;q ++) 
				if(a[q] != x) 
					tmp.push_back(a[q]);
				
			
			// for (int t : tmp) cout << t << \' \';cout << endl;
			for (int i = 1;i <= k;i ++) pos[a[i]] = i;
			a = tmp;
			ans += pos[x];
		
	
	cout << ans << endl;

C Simple Strings

做法:氵题,模拟。
代码:

void solve()
	string s;
	cin >> s;
	int n = s.length();
	s = " " + s;
	for (int i = 1;i <= n;i ++) 
		if(s[i - 1] == s[i]) 
			if(i + 1 <= n) 
				for (char op = \'a\';op <= \'z\';op++) 
					if(op != s[i - 1] && op != s[i + 1]) s[i] = op;
				
			
			else 
				for (char op = \'a\';op <= \'z\';op++) 
					if(op != s[i - 1]) s[i] = op;
				
			
		
	
	for (int i = 1;i <= n;i ++) cout << s[i];cout << endl;

D Simple Subset

做法:需要点神奇思路的题,我们首先考虑这么个情况,假设现在存在三个数,如果其中不含\\(1\\)的话,是不可能满足题目的要求的,我们可以从奇偶性的角度出发,三个数之中,全为奇或偶必寄,剩下的就是有两个为奇,两个为偶这个样子,那么我们就可以发现,因为奇数加奇数为偶数,偶数不可能为素数,所以,三个数寄。
根据样例知道,我们要特判\\(1\\),即可解答。
代码:

int primes[N];
bool st[N];
int cnt;
void init() 
	for (int i = 2;i < N;i ++) 
		if(!st[i]) primes[cnt++] = i;
		for (int j = 0;j < cnt && primes[j] * i < N;j ++) 
			st[primes[j] * i] = 1;
			if(i % primes[j] == 0) break;
		
	

void solve()
	int n;
	cin >> n;
	vector<int> a(n + 1);
	int cnt1 = 0;
	for (int i = 1;i <= n;i ++) 
		cin >> a[i];
		if(a[i] == 1) cnt1++;
	
	if(cnt1 == 0 || cnt1 == 1) 
		for (int i = 1;i <= n;i ++) 
			for (int j = i + 1;j <= n;j ++) 
				if(!st[a[i] + a[j]]) 
					cout << 2 << endl;
					cout << a[i] << \' \' << a[j] << endl;
					return ;
				
			
		
		cout << 1 << endl;
		cout << a[1] << endl;
	
	else 
		for (int i = 1;i <= n;i ++) 
			if(!st[a[i] + 1] && a[i] != 1) 
				cout << cnt1 + 1 << endl;
				for (int i = 1;i <= cnt1;i ++) cout << 1 << \' \';
				cout << a[i] << endl;
				return ;
			
		
		cout << cnt1 << endl;
		while(cnt1--) cout << 1 << \' \';cout << endl;
	

E Beautiful Subarrays

做法:队友点评为典,对于这个问题我们可以这么考虑,我们如果把题目要求改成异或值等于\\(k\\),那么是不是就很简单了,直接前缀异或和等于k,\\(O(n)\\)的复杂度。但是这里是大于等于\\(k\\),我们考虑建trie树来考虑异或值,从高到低位进行贪心的选择,如果遍历到的这一位为1的话,因为是从高到底考虑的,所以这一位的异或值必须为\\(1\\),对于当前的\\(R_i\\),我们走置反的路,\\(0\\)\\(1\\)\\(1\\)\\(0\\)
如果这一位为\\(0\\),那我们考虑异或为\\(1\\)时肯定最优,所以把异或为1时的子树加入贡献,这里trie的cnt统计为经过每个点的数量,即可做出本题。
代码:

int son[N * 30][2];
int cnt[N * 30];
int idx;
int k;
void insert(int x) 
	int p = 0;
	for (int i = 30;i >= 0;i --) 
		int &s = son[p][x >> i & 1];
		if(!s) s = ++idx;
		p = s;
		cnt[p]++;
	

int find(int x) 
	int p = 0;
	int res = 0;
	ll ans = 0;
	for (int i = 30;i >= 0;i --) 
		int ck = (k >> i) & 1;
		if(ck == 1) 
			p = son[p][!(x >> i & 1)];
		else 
			ans += cnt[son[p][!(x >> i & 1)]];
			p = son[p][(x >> i & 1)];
		
		if(!p) break;
	
	ans += cnt[p];
	return ans;

void solve()
	int n;
	cin >> n >> k;
	vector<int> a(n + 1);
	for (int i = 1;i <= n;i ++) cin >> a[i];
	ll s = 0;
	insert(0);
	ll ans = 0;
	for (int i = 1;i <= n;i ++) 
		s ^= a[i];
		ans += find(s);
		insert(s);
	
	cout << ans << endl;

F Four Divisors

做法:这题做法及其简单,难点在于算法。
考虑有四个因子的数,根据因子个数的定理,质因数的次数要么为\\(4\\)要么为两个\\(1\\)
所以我们需要的是能做到快速的计算\\(\\pi(n)\\),这里套用了别人的Messiel-Lermer的板子,这个算法现在看的还不是很懂,就是黑盒的用了一下。
代码:

namespace pcf
    long long dp[MAXN][MAXM];
    unsigned int ar[(MAX >> 6) + 5] = 0;
    int len = 0, primes[MAXP], counter[MAX];
 
    void Sieve()
        setbit(ar, 0), setbit(ar, 1);
        for (int i = 3; (i * i) < MAX; i++, i++)
            if (!chkbit(ar, i))
                int k = i << 1;
                for (int j = (i * i); j < MAX; j += k) setbit(ar, j);
            
        
 
        for (int i = 1; i < MAX; i++)
            counter[i] = counter[i - 1];
            if (isprime(i)) primes[len++] = i, counter[i]++;
        
    
 
    void init()
        Sieve();
        for (int n = 0; n < MAXN; n++)
            for (int m = 0; m < MAXM; m++)
                if (!n) dp[n][m] = m;
                else dp[n][m] = dp[n - 1][m] - dp[n - 1][m / primes[n - 1]];
            
        
    
 
    long long phi(long long m, int n)
        if (n == 0) return m;
        if (primes[n - 1] >= m) return 1;
        if (m < MAXM && n < MAXN) return dp[n][m];
        return phi(m, n - 1) - phi(m / primes[n - 1], n - 1);
    
 
    long long Lehmer(long long m)
        if (m < MAX) return counter[m];
 
        long long w, res = 0;
        int i, a, s, c, x, y;
        s = sqrt(0.9 + m), y = c = cbrt(0.9 + m);
        a = counter[y], res = phi(m, a) + a - 1;
        for (i = a; primes[i] <= s; i++) res = res - Lehmer(m / primes[i]) + Lehmer(primes[i]) - 1;
        return res;
    

void solve()
	int n;
	pcf::init();
	cin >> n;
	int ans = 0;
	for (int i = 0;i < pcf::len;i ++) 
		int p = pcf::primes[i];
		int y = n / p;
		if(p > sqrt(n)) break;
		else ans += pcf::Lehmer(y) - pcf::Lehmer(p);
	
	for (int i = 0;i < pcf::len;i++) 
		int p = pcf::primes[i];
		if(p * p * p > n) break;
		else ans++;
	
	cout << ans << endl;

 

以上是关于Educational Codeforces Round 12的主要内容,如果未能解决你的问题,请参考以下文章

Educational Codeforces Round 7 A

Educational Codeforces Round 7

Educational Codeforces Round 90

Educational Codeforces Round 33

Codeforces Educational Codeforces Round 54 题解

Educational Codeforces Round 27