Codeforces Round #632 (Div. 2) D. Dreamoon Likes Sequences (思维 + 乘法原理)
Posted lasomisolaso~
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #632 (Div. 2) D. Dreamoon Likes Sequences (思维 + 乘法原理)相关的知识,希望对你有一定的参考价值。
思维+乘法原理
题意:
给出一个上限 d d d,和一个模数 m m m,计算符合下列条件的数列 a a a的个数:
- 数列 a a a的长度大于等于 1 1 1。
- 数列 a a a的最小值大于等于 1 1 1,最大值小于等于 d d d,且是严格单调递增的。
- 对于
a
a
a用如下方式构造一个数列
b
b
b, 要求构造的数列
b
b
b是严格单调递增的。
b 1 = a 1 b_1 = a_1 b1=a1
b i = b i − 1 ⨁ a i ( i ≥ 1 ) b_i = b_i -1 \\bigoplus a_i (i \\geq 1) bi=bi−1⨁ai(i≥1)
题解:
参考官方题解:
首先定义一个函数
h
(
a
i
)
h(a_i)
h(ai),表示
a
i
a_i
ai的二进制表示中数位为1的最高位是哪一位。比如
h
(
10
)
=
3
h(10) = 3
h(10)=3。由a是严格单调递增的条件我们可以知道,
h
(
a
i
+
1
)
>
=
h
(
a
i
)
h(a_i+1) >= h(a_i)
h(ai+1)>=h(ai)。
然后我们利用b是严格单调递增的条件,
b
2
=
a
1
⨁
a
2
,
b
2
>
b
1
b_2 = a_1 \\bigoplus a_2, b_2 > b_1
b2=a1⨁a2,b2>b1。可以知道
h
(
a
2
)
>
h
(
a
1
)
h(a_2) > h(a_1)
h(a2)>h(a1),如果
h
(
a
2
)
=
h
(
a
1
)
h(a_2) = h(a_1)
h(a2)=h(a1)的话,那么异或之后这个最高位将会变成0,导致
b
2
<
b
1
b_2 < b_1
b2<b1。
同时我们也可以得出
h
(
b
2
)
=
h
(
a
2
)
h(b_2) = h(a_2)
h(b2)=h(a2)。依次类推就可以得出
h
(
b
i
)
=
h
(
a
i
)
,
h
(
a
i
+
1
)
>
h
(
a
i
)
h(b_i) = h(a_i), h(a_i+1) > h(a_i)
h(bi)=h(ai),h(ai+1)>h(ai)。
每一个 h ( a i ) h(a_i) h(ai)都是不同的,且是严格递增的。那么在符合条件的数列中,只有一个 a i a_i ai或者没有 a i a_i ai满足 h ( a i ) = v h(a_i) = v h(ai)=v。也就是只有一个或者没有 a i a_i ai属于 [ 2 v , m i n ( 2 v + 1 − 1 , d ) ] [2^v, min(2^v +1 - 1, d)] [2v,min(2v+1−1,d)]。只要从每一个数段中选出一个数,或者不选,这样组成的数列从小到大排序都是合法的。每一段有 m i n ( 2 v + 1 − 1 , d ) − 2 v + 2 min(2^v+1 - 1, d) - 2^v+2 min(2v+1−1,d)−2v+2个选择。根据乘法原理就可求出总数,最后要减去每一个都不选形成的数列。
代码:
/**
* Author : Xiuchen
* Date : 2020-04-07-12.02.25
* Description : 乘法原理
*/
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#include<cstdio>
#include<cstring>
#include<string>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<cmath>
#include<math.h>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3fLL;
//const int maxn = ;
int gcd(int a, int b)
return b ? gcd(b, a % b) : a;
int t;
ll d, m;
int main()
cin >> t;
while(t--)
cin >> d >> m;
ll ans = 1 % m;
for(int i = 0; i <= 31; i++)
ll tmp = 1 << i;
if(tmp > d) break;
ll num = min((1ll << (i + 1)) - 1, d) - tmp + 2;
ans = ans * num % m;
cout << (ans - 1 + m) % m << endl;
return 0;
以上是关于Codeforces Round #632 (Div. 2) D. Dreamoon Likes Sequences (思维 + 乘法原理)的主要内容,如果未能解决你的问题,请参考以下文章
[每日一题]:Codeforces Round #632 (Div. 2) C. Eugene and an array
Codeforces Round #632 (Div. 2) D. Dreamoon Likes Sequences (思维 + 乘法原理)
Codeforces Round #632 (Div. 2)F. Kate and imperfection(逆向贪心因子)
Codeforces Round #632 (Div. 2)F. Kate and imperfection(逆向贪心因子)