[luogu 3773][CTSC 2017]吉夫特
阿新 • • 發佈:2018-11-25
傳送門
Solution
輸入一個長度為n的數列,求有多少個長度大等於2的不上升子序列滿足:
\[\prod_{i=2}^{k} C(a_{b_{i-1}},a_{b_i}) mod\ 2 >0 \]
答案對1e9+7取模
根據Lucas定理:
\[C\ (n,\ m)\ ≡\ C\ (\frac{n}{p},\frac{m}{p})*\ C\ (n\%p,\ m\%p)\ (mod\ p)\]
可以發現,只要滿足m是n的子集,或者說是(n&m)=m
即可。
令f[i]
表示從\(a_i\)開始的序列的數量,轉移時列舉 \(a_i\)
因為我們的\(a_i\)時互不相同的,所以,複雜度大概是\(O(3^{\log \max a_i})\)
寫部落格的真實原因其實是,pac弱到連列舉子集都不會
#include<bits/stdc++.h> #define ll long long #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) #define swap(x,y) (x^=y^=x^=y) inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} return x*f; } #define MN 211990 #define MM 233335 #define mod 1000000007 int a[MN],pos[MM],f[MN]; int n,ans; inline void add(int &x,int y){x+=y;x>=mod?x-=mod:0;} int main() { n=read(); register int i,j; for(i=1;i<=n;++i) a[i]=read(),pos[a[i]]=i; for(i=n;i;--i) { f[i]=1; for(j=a[i]&(a[i]-1);j;j=a[i]&(j-1)) if(pos[j]>i) add(f[i],f[pos[j]]); add(ans,f[i]); } add(ans,mod-n); printf("%d\n",ans); return 0; }
所以呢,如何列舉子集?
for(i=S;i&=S;--i)
Blog來自PaperCloud,未經允許,請勿轉載,TKS!