【题解】[LOJ #2264 / 洛谷 P3773] 吉夫特【计数DP】
作者:互联网
题意
求给定序列有多少长度大于 \(1\) 的子序列,满足 \(\prod_{i=2}^k \dbinom{a_{b[i-1]}}{a_{b[i]}}\)。\(a_i\) 互不相同。\(n\leq 211985\),\(a_i\leq 233333\)。
题解
根据 Lucas 定理,子序列中前面的数一定是后面的数(二进制下)的超集。于是枚举子集(或超集,取决于 DP 的顺序)转移。因为 \(a_i\) 互不相同,复杂度大概是 \(O(3^k)\)(\(k\) 为位数)(假设值很大)。
// Accepted FLOJ 3
// https://floj.tech/submission/144950
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int BUF_LEN=1<<19;
struct FastIO{
char bufi[BUF_LEN+10],*PTi=bufi+BUF_LEN,*PTENDi=bufi+BUF_LEN;
inline char gc(){
(PTi==PTENDi)&&(bufi[fread(bufi,1,BUF_LEN,stdin)]=0,PTi=bufi);
return *(PTi++);
}
char bufo[BUF_LEN+10],*PTo=bufo,*PTENDo=bufo+BUF_LEN;
inline void pc(char c){
(PTo==PTENDo)&&(fwrite(bufo,1,BUF_LEN,stdout),PTo=bufo);
*(PTo++)=c;
}
void flush(){
fwrite(bufo,1,PTo-bufo,stdout);
PTo=bufo;
}
~FastIO(){
flush();
}
template<class T>inline void getint(T &x=0){
char c=gc();
int f=1;x=0;
while(c<'0'||c>'9'){
if(c=='-')f=-1;
c=gc();
}
while(c>='0'&&c<='9'){
x=x*10+c-'0';
c=gc();
}
if(f==-1)x=-x;
}
operator int(){
int v;getint(v);return v;
}
operator long long(){
long long v;getint(v);return v;
}
template<class T>inline void putint(T x=0,char sep=' '){
char tmp[20],len=0;
if(x<0)pc('-'),x=-x;
if(x==0){ pc('0');pc(sep);return; }
while(x)tmp[len++]=x%10,x/=10;
for(int i=len-1;~i;--i)pc(tmp[i]|'0');
pc(sep);
}
}io;
#define uint unsigned int
const int N=1<<18,mod=1e9+7;
int f[N],a[N];
int main(){
int n(io);
for(int i=0;i<n;i++)a[i]=io;
reverse(a,a+n);
f[0]=1;
for(int i=0;i<n;i++){
int x(a[i]);
for(int i=x;;i=x&(i-1)){
f[x]+=f[i];
f[x]>=mod&&(f[x]-=mod);
if(!i)break;
}
}
int ans=0;
for(int i=0;i<N;i++)ans+=f[i],ans>=mod&&(ans-=mod);
io.putint((ans-n-1+mod)%mod);
}
标签:洛谷,int,题解,char,&&,ans,夫特,include,mod 来源: https://www.cnblogs.com/wallbreaker5th/p/14218839.html