题目链接
题目大意
让你构造一个严格单调上升的数组a满足\(1<=a_1<a_2<....a_n<=d\)
而且要使得这个数组的异或前缀和也满足严格单调上升,求有多少个满足条件的数组(mod m)
题目思路
首先这个数组的性质很容易观察就是后一个数化为二进制的最高位1要比第上一个高
然后我就不会了
我还以为是枚举数组长度啥的,果然是我太菜了
这种类型的题目需要求贡献。枚举位数为 i 的数是否在序列中出现并计算对答案的贡献,根据乘法原理相乘即答案。
当位数小于log(d)的位数,贡献则为\(2^i+1\)(位数为i的个数或不出现)
还要注意减去n=0的情况
代码
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
#define fi first
#define se second
#define debug printf(" I am here\n");
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int maxn=2e5+5,inf=0x3f3f3f3f,mod=1e9+7;
const double eps=1e-10;
int d,m;
signed main(){
int _;scanf("%d",&_);
while(_--){
scanf("%d%d",&d,&m);
ll ans=1;
for(int i=0;(1<<i)<=d;i++){
ans=ans*(min((1<<i)+1,d-((1<<i)-1)+1))%m;
//可以选(1<<i)或者不选+1
}
ans=(ans-1+m)%m;//数列不能为0
printf("%lld\n",ans);
}
return 0;
}