牛客提高R5 A.同余方程
題意
題目鏈接
Sol
設\(solve(x, y)\)表示\(i \in [0, x], j \in [0, y]\)滿足題目要求的方案數
首先容斥一下,\(ans = solve(r_1, r_2) - solve(l_1 - 1, r_2) - solve(l_2 - 1, r_1) + solve(l_1 -1, l_2 - 1)\)
然后按照套路按位拆分,這里拆的時候是直接對\(x, y\)進行拆分
這樣就把問題轉換成了看起來似乎簡單一些的問題
假設拆完后的數是
110011101
1011
我們只要對于任意一對為1的位,求出小于該位的所有合法解即可
比如\(i = 3, j = 1\)我們要計算的就是\([110010000, 110010111]\)與\([1000, 1001]\)內的合法解
兩種都可以寫成\([v, v + 2^k]\)的性質
先考慮一種簡單的情況,即\(v = 0\)
假設\(i > j\),那么\(\forall z = x \oplus y \leqslant 2^i\), 對于任意的\(x \leqslant 2^j\),都會有唯一的\(y\)與之對應
那么我們只要數出\([0, 2^i]\)中\(\% M == 0\)的數的個數,再乘上\(2^j\)即可
存在\(a[i]\)的限制實際上是一樣的。
但是這樣統計到的實際上是開區間的信息,只要在右端點處+1即可
#include<iostream> #include<algorithm> #define LL long long using namespace std; const LL mod = 998244353; LL l1, r1, l2, r2, M; LL add(LL x, LL y) {return (x + y >= mod) ? (x + y - mod) : (x + y); } LL calc(LL l, LL r) {if(l == 0) return ((r / M) + 1) % mod;return (r / M - (l - 1) / M) % mod; } LL solve(LL X, LL Y) {LL ans = 0;for(LL i = 0, p1 = X; p1; i++, p1 >>= 1) {for(LL j = 0, p2 = Y; p2; j++, p2 >>= 1) {if((p1 & 1) && (p2 & 1)) {LL x = i, y = j; if(x < y) swap(x, y);LL ll = ((((p1 ^ 1) << i) ^ ((p2 ^ 1) << j)) >> x) << x;ans = add(ans, (1ll << y) % mod * calc(ll, ll + (1ll << x) - 1) % mod);//cout << ans << endl;}}} // cout << ans << endl;return ans; } int main() {cin >> l1 >> r1 >> l2 >> r2 >> M;cout << (solve(r1 + 1, r2 + 1) - solve(l1, r2 + 1) + mod - solve(r1 + 1, l2) + mod + solve(l1, l2) + mod) % mod;return 0; } /* 1 1 1 1 1 */轉載于:https://www.cnblogs.com/zwfymqz/p/9800078.html
總結
以上是生活随笔為你收集整理的牛客提高R5 A.同余方程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JS高级——变量提升
- 下一篇: MapReduce编程中常用的字符操作