UOJ300吉夫特

来源:互联网 发布:config.php 编辑:程序博客网 时间:2024/06/06 00:43

传送门
我真是智障,明明知道Lucas定理,却不知道
(nm)1(modn)等价于(n2m2)(n2m2)1(modn)
然后(n2m2)不等于零,等价于二进制下,n的末位大于等于m。再结合(n2m2),可以推知(nm)1(modn)等价于n&m==m。
设s为值域(等于ai的最大值)
然后我看漏了所以ai都互不相等,作死写了个O(ns12)按前9位暴力,后九位前缀和的分块做法。实际上,因为ai互不相等,所以暴力枚举子集是O(3(log2s))(其中s是为O(n)),约为O(ns0.581)

#include<cstdio>typedef long long ll;const int N=300000; const ll mo=1000000007;int n,i,f[N],j,g[N],a[N],ans,x,y,s[513][513],all=(1<<9)-1;int main(){    //freopen("ex_gift9.in","r",stdin);    scanf("%d",&n);    for(i=1;i<N;++i)f[i]=f[i>>1]+(i>>1);    for(i=1;i<=n;++i)scanf("%d",a+i);    for(i=1;i<=n;++i){        for(x=a[i]>>9,y=a[i]&all,j=all^x;;j=(j-1)&(all^x)){            g[i]=(s[all^j][y]+g[i])%mo;            if(!j)break;        }        ans=(ans+g[i])%mo;        g[i]=(g[i]+1)%mo;        for(j=y;;j=(j-1)&y){            s[x][j]=(s[x][j]+g[i])%mo;            if(!j)break;        }    }    printf("%d\n",ans);    return 0;}