其他分享
首页 > 其他分享> > arc141 B - Increasing Prefix XOR

arc141 B - Increasing Prefix XOR

作者:互联网

题意:

给定 \(n,m\),问有多少数组 \(a[]\) 满足:

\(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