[codeforces 1330D] Dreamoon Likes Sequences 数据分组+乘法原理

Codeforces Round #631 (Div. 2) - Thanks, Denis aramis Shitov!   比赛人数10889

[codeforces 1330D]   Dreamoon Likes Sequences   数据分组+乘法原理

总目录详见https://blog.csdn.net/mrcrack/article/details/103564004

在线测评地址https://codeforces.com/contest/1330/problem/D

Problem Lang Verdict Time Memory
D - Dreamoon Likes Sequences GNU C++11 Accepted 31 ms 0 KB

因有小伙伴不熟悉异或运算,作简单介绍,异或是不进位的加法,举例如下

以下运算发生在二进制情况下,0,1均对应二进制数
1^0=1
0^1=1
1^1=0

算法核心:根据异或的性质可以得出,2后边不能有3, 4后边不能有5~7, 8后边不能有9~15...... 然后就很好写了.

理由如下(摘自https://www.cnblogs.com/KisekiPurin2019/p/12635707.html):

手工算法如下

4 9999997

11

原始数据    1    2    3    4
十进制形式  1    2    3    4
二进制形式  1    10   11   100

谈谈数组a的11种组合由来:
1.暴力枚举,11种组合如下:
1
2
3
4
1,2
1,3
1,4
2,4
3,4
1,2,4
1,3,4
2.数据分组+乘法原理:
以上述数据为例,将1,2,3,4进行数据分组
(1) (2 3) (4)
在每组里进行选择
(1)这组数据的选择:只选1,什么都不选,共计2种选择
(2 3)这组数据的选择:只选2,只选3,什么都不选,共计3种选择
(4)这组数据的选择:只选4,什么都不选,共计2种选择

根据排列组合中的乘法原理,(1) (2 3) (4)这3组数据选择对应的组合数是
2*3*2=12
请注意,上述组合数中,包含了一种情况,所有的数据分组中的元素都不选,即空集的情况,这种情况需扣除,故最终答案是
12-1=11

再举一例

9 92

89
以上述数据为例,将1,2,3,4,5,6,7,8,9进行数据分组
(1) (2 3) (4 5 6 7) (8 9)
在每组里进行选择
(1)这组数据的选择:只选1,什么都不选,共计1+1=2种选择
(2 3)这组数据的选择:只选2,只选3,什么都不选,共计2+1=3种选择
(4 5 6 7)这组数据的选择:只选4,只选5,只选6,只选7,什么都不选,共计4+1=5种选择
(8 9)这组数据的选择:只选8,只选9,什么都不选,共计2+1=3种选择

根据排列组合中的乘法原理,(1) (2 3) (4 5 6 7) (8 9)这4组数据选择对应的组合数是
2*3*5*3=90
请注意,上述组合数中,包含了一种情况,所有的数据分组中的元素都不选,即空集的情况,这种情况需扣除,故最终答案是
90-1=89


手工算法熟练后,规律也就容易掌握,可以考虑开始编码,读者若有不明,可以继续看接下来的AC代码

#include <cstdio>
#include <cmath>
#define LL long long
using namespace std;
int main(){
	int t,d,m,i,p;
	LL ans;
	scanf("%d",&t);
	while(t--){
		scanf("%d%d",&d,&m);
		ans=1,p=log2(d);//log2()以2为底的对数
		for(i=0;i<p;i++)ans=ans*((1<<i)+1)%m;//+1是指该组元素什么都不选的情况
		ans=ans*(d-(1<<p)+1+1)%m;//最后一组数据区间计算,第1个+1是(1<<p)这个数据,第2个+1是该组元素什么都不选的情况
		ans=((ans-1)%m+m)%m;//-1是需扣除,所有分组,什么元素都不选,即空集的情况.还考量了ans可能出现负数的情况.
		printf("%lld\n",ans);
	}
	return 0;
}
发布了660 篇原创文章 · 获赞 562 · 访问量 48万+

猜你喜欢

转载自blog.csdn.net/mrcrack/article/details/105337947