题目链接
题目思路
首先要观察它需要的数是小于\(2^p\),那么需要往二进制的思路去想就简单很多
\(x=2y+1\) 本质上就是在二进制的表现下末尾加一个1
\(x=4y\) 本质上就是在二进制的表现下末尾加两个\(00\)
那么如果一个二进制长度为\(len\)的数\(x\)
它要延申成长度为\(len+1\)位有\(1\)种
它要延申成长度为\(len+2\)位有\(2\)种
它要延申成长度为\(len+3\)位有\(3\)种
这就是斐波那契数列
定义\(\sum_{i=0}^{i=n} fac[i]=sum[n]\)
那么如果他要延申成长度小于\(p\)位有\(sum[p-len]\)种
那么对于一个数的情况解决了,那么对于多个数的情况就是需要去重
加入\(x\)可以生成\(y\),那么需要去掉\(y\)
那么假如\(y\)是奇数,\(y/=2\) 。假如\(y\)是\(4\)的倍数,\(y/=4\) 看中途是否出现过即可
代码
#include<bits/stdc++.h>
#define fi first
#define se second
#define debug cout<<"I AM HERE"<<endl;
using namespace std;
typedef long long ll;
const int maxn=2e5+5,inf=0x3f3f3f3f,mod=1e9+7;
const double eps=1e-6;
int n,p;
int a[maxn];
ll ans;
ll fac[maxn],sum[maxn];
map<int, bool> mp;
int cal(int x){
int len=0;
while(x){
x/=2;
len++;
}
return len;
}
signed main(){
fac[0]=fac[1]=1;
sum[0]=1;
sum[1]=2;
for(int i=2;i<=2e5;i++){
fac[i]=(fac[i-1]+fac[i-2])%mod;
sum[i]=(sum[i-1]+fac[i])%mod;
}
scanf("%d%d",&n,&p);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
mp[a[i]]=true;
}
for(int i=1;i<=n;i++){
int tmp=a[i];
bool flag=false;
while(tmp){
if(tmp%2){
tmp/=2;
}else if(tmp%4==0){
tmp/=4;
}else{
break;
}
if(mp.count(tmp)){
flag=true;
break;
}
}
if(flag) continue;
int len=cal(a[i]);
if(p-len>=0){
ans=(ans+sum[p-len])%mod;
}
}
printf("%lld\n",ans);
return 0;
}
题目链接
题目思路
首先要观察它需要的数是小于\(2^p\),那么需要往二进制的思路去想就简单很多
\(x=2y+1\) 本质上就是在二进制的表现下末尾加一个1
\(x=4y\) 本质上就是在二进制的表现下末尾加两个\(00\)
那么如果一个二进制长度为\(len\)的数\(x\)
它要延申成长度为\(len+1\)位有\(1\)种
它要延申成长度为\(len+2\)位有\(2\)种
它要延申成长度为\(len+3\)位有\(3\)种
这就是斐波那契数列
定义\(\sum_{i=0}^{i=n} fac[i]=sum[n]\)
那么如果他要延申成长度小于\(p\)位有\(sum[p-len]\)种
那么对于一个数的情况解决了,那么对于多个数的情况就是需要去重
加入\(x\)可以生成\(y\),那么需要去掉\(y\)
那么假如\(y\)是奇数,\(y/=2\) 。假如\(y\)是\(4\)的倍数,\(y/=4\) 看中途是否出现过即可
代码
#include<bits/stdc++.h>
#define fi first
#define se second
#define debug cout<<"I AM HERE"<<endl;
using namespace std;
typedef long long ll;
const int maxn=2e5+5,inf=0x3f3f3f3f,mod=1e9+7;
const double eps=1e-6;
int n,p;
int a[maxn];
ll ans;
ll fac[maxn],sum[maxn];
map<int, bool> mp;
int cal(int x){
int len=0;
while(x){
x/=2;
len++;
}
return len;
}
signed main(){
fac[0]=fac[1]=1;
sum[0]=1;
sum[1]=2;
for(int i=2;i<=2e5;i++){
fac[i]=(fac[i-1]+fac[i-2])%mod;
sum[i]=(sum[i-1]+fac[i])%mod;
}
scanf("%d%d",&n,&p);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
mp[a[i]]=true;
}
for(int i=1;i<=n;i++){
int tmp=a[i];
bool flag=false;
while(tmp){
if(tmp%2){
tmp/=2;
}else if(tmp%4==0){
tmp/=4;
}else{
break;
}
if(mp.count(tmp)){
flag=true;
break;
}
}
if(flag) continue;
int len=cal(a[i]);
if(p-len>=0){
ans=(ans+sum[p-len])%mod;
}
}
printf("%lld\n",ans);
return 0;
}