arc141 B - Increasing Prefix XOR
作者:互联网
题意:
给定 \(n,m\),问有多少数组 \(a[]\) 满足:
- \(1\le a_1< a_2 < \cdots < a_n \le m\)
- \(b_1<b_2<\cdots <b_n\),其中 \(b[]\) 为前缀异或和即 \(b_i=a_1\oplus a_2\oplus \cdots \oplus a_i\)
\(1\le n \le m<2^{60}\)
思路:
\(a_i<a_{i+1}\) 则 \(a_{i+1}\) 的位数不少于 \(a_i\) 的位数(位数指二进制位数)
\(b_i<b_{i+1}=b_i\oplus a_{i+1}\) 则 \(a_{i+1}\) 的位数不等于 \(b_i\) 的位数
所以若 \(a_i\) 和 \(b_i\) 有相同的位数,则 \(a_{i+1}\) 的位数严格大于 \(a_i\) 和 \(b_i\) 的位数
而 \(a_1=b_1\implies a_1\) 和 \(b_1\) 位数相同 \(\implies a_2\) 的位数严格大于 \(a_1,b_1\) 的位数 \(\implies b_2\) 的位数等于 \(a_2\) 的位数
以此类推得 \(a_i\) 的位数严格递增就行了!
因为 \(m<2^{60}\) 所以 \(m\) 最多有 60 位,所以当 \(n>60\) 时答案为 0
\(n\le 60\) 时 dp 一下:\(f(i,j)\) 表示 \(n=i\),\(a_i\) 有 \(j\) 位
ll n, m, f[N][N], g[N]; //恰有i位的数有几个
void sol()
{
cin >> n >> m;
if (n > 60)
return cout << 0, void();
int dig = log2(m) + 1;
g[dig] = m; //预处理g[]
for (int i = 1; i < dig; i++)
g[i] = qmi(2, i - 1), g[dig] = add(g[dig], -g[i]);
f[0][0] = 1;
for (int i = 1; i <= n; i++)
for (int j = i; j <= dig; j++) //当前位数
for (int k = 0; k < j; k++) //上一个位数
f[i][j] = add(f[i][j], mul(g[j], f[i - 1][k]));
ll ans = 0;
for (int i = 1; i <= dig; i++)
ans = add(ans, f[n][i]);
cout << ans;
}
标签:le,XOR,60,严格,arc141,位数,大于,implies,Increasing 来源: https://www.cnblogs.com/wushansinger/p/16351522.html