Codeforces 1557c moamen and XOR (combinatorial thinking)

Posted by mr.rum on Sat, 01 Jan 2022 19:21:54 +0100

Title Link: Moamen and XOR

General meaning

Given n and k, let you construct a length of n n Sequence a [], each element less than 2 k 2^k 2k​​.

Requirement sequence satisfied a 1 a_1 a1​ & a 2 a_2 a2​ & a 3 a_3 a3​ & ... & a n a_n an​ ≥ a 1 a_1 a1​ ⊕ a 2 a_2 a2​ ⊕ a 3 a_3 a3​ ⊕ ... ⊕ a n a_n an​​

Q: there are two sequences that meet the requirements

Problem solving ideas

thinking

The numbers mentioned below are in binary form!!! For simplicity, remember a n d and and is the result on the left of the original formula, x o r xor xor is the result on the right

We first default that all bits are 1, then there must be and == xor
Next, let's consider reducing the number Since the change of the high bit will directly affect the size of the number, we consider the case of the highest bit:

The highest order is all 1:
If n is an odd number, it indicates a n d and And , and x o r xor The highest order of xor , is 1, which is equal. We need to continue to analyze the second highest order
At this time, the answer contribution = the answer contribution of the second highest position

If n is an even number, it indicates a n d and The highest bit of and is 1, and x o r xor The highest bit of xor , is 0, which is when and is greater than xor At this time, other bits can be arranged arbitrarily, all satisfying and > xor
At this time, the answer contribution = the total number of fully arranged schemes in other positions

Suppose it's the second i i i bit, then there is j = i − 1 j = i - 1 j=i − 1 can be fully arranged, and each position has two values of 01, so one number has two values in common 2 j 2^j In 2j cases, there are n numbers in total, so the total number of schemes is: ( 2 j ) n (2^j)^n (2j)n

The highest bit is not all 1:
We consider changing part 1 to bit 0 At this time, the highest bit of and must be 0, so the highest bit of xor must also be 0, then there must be an even number of 1 at the highest bit

If n is an odd number, we can select {1, 3, 5,..., n} positions so that their highest order becomes 0
If n is an even number, we can select {2, 4, 6,..., n} positions so that their highest position becomes 0

The way to select these locations is:

Odd: s u m = C n 1 + C n 3 + . . . + C n n sum = C_n^1 + C_n^3 + ... + C_n^n sum=Cn1​+Cn3​+...+Cnn​​

even numbers: s u m = C n 2 + C n 4 + . . . + C n n sum = C_n^2 + C_n^4 + ... + C_n^n sum=Cn2​+Cn4​+...+Cnn​​​​

At this time, the answer contribution = sum * the scheme contribution of the second highest order

So far, we have analyzed all the situations. When analyzing the other bits, we think that there is no similar analysis for the high bits We found that it should be discussed in categories That is, it is classified according to the parity of n

Let dp[], dp[i] represent the contribution of bit I

When n is odd: d p [ i ] = d p [ i − 1 ] ∗ ( 1 + s u m ) dp[i] = dp[i - 1] * (1 + sum) dp[i]=dp[i − 1] * (1+sum) where 1 is the scheme when bit I is all 1 and sum is the scheme when bit I is not all 1

When n is even: d p [ i ] = d p [ i − 1 ] ∗ ( ( 2 i − 1 ) n + s u m ) dp[i] = dp[i - 1] * ((2^{i-1})^{n} + sum) dp[i]=dp[i − 1] * ((2i − 1)n+sum) where ( 2 i − 1 ) n (2^{i-1})^{n} (2i − 1)n is the scheme when the ith bit is all 1, and sum is the scheme when the ith bit is not all 1

If you have any questions about this blog, please leave a message in the comment area and I will reply to you tonight

AC code

#include <bits/stdc++.h>
#define rep(i, n) for (int i = 1; i <= (n); ++i)
using namespace std;
typedef long long ll;
const int N = 2E5 + 10, mod = 1E9 + 7;
int fpow(int a, int b) { //Counting 
	ll res = 1; a %= mod;
	while (b) {
		if (b & 1) res = res * a % mod;
		b >>= 1;
		a = 1ll * a * a % mod;
	}
	return res;
}


/* Combinatorial mathematics */
int num[N], innum[N];
void init(int n = N - 5)
{
	num[0] = innum[0] = 1;
	for (int i = 1; i <= n; ++i) {
		num[i] = 1ll * num[i - 1] * i % mod;
		innum[i] = 1ll * innum[i - 1] * fpow(i, mod - 2) % mod; //Inverse element
	}
}
int C(int a, int b) { return 1ll * num[a] * innum[a - b] % mod * innum[b] % mod; }


/* Processing combination prefix */
int calcodd(int n) {
	ll res = 0;
	for (int i = 1; i <= n; i += 2) res = (res + C(n, i)) % mod;
	return res;
}
int calceven(int n) {
	ll res = 0;
	for (int i = 2; i <= n; i += 2) res = (res + C(n, i)) % mod;
	return res;
}
int dp[N];
int main()
{
	init(); // It can't be true? Did you write combinatorics and forget to call init()?
    
	int t; cin >> t;
	while (t--) {
		int n, k; scanf("%d %d", &n, &k);

		dp[0] = 1;
		if (n & 1) {
			int sum = calcodd(n);
			for (int i = 1; i <= k; ++i) {
				dp[i] = 1ll * dp[i - 1] * (1 + sum) % mod;
			}
		}
		else {
			int sum = calceven(n);
			for (int i = 1; i <= k; ++i) {
				dp[i] = 1ll * dp[i - 1] * sum % mod;
				dp[i] = (dp[i] + fpow(fpow(2, i - 1), n)) % mod;
			}
		}
		printf("%d\n", dp[k]);
	}
    
	return 0;
}

END

Topics: Algorithm Dynamic Programming number theory CodeForces