有n個人每個人有乙個字符集初始為空。
有tot個事件,每個事件形如在第ai個人的字符集裡放了bi這個小寫字母。
每個時刻等概率發生乙個事件。
有乙個長度為m的字串s。某個時刻如果存在編號連續的m個人,按從小到大的順序發現對於第i個人字符集裡都有si,那麼則勝利。
問勝利的期望時間,要求判斷無解,答案在模意義下進行。設f
(i) 表示時刻i還沒有勝利的概率。
答案是∑
i>=0f
(i)
考慮容斥,列舉哪些位置作為起點在時刻t匹配成功。 f(
t)=∑
2n−m
+1−1
i=0g
(h(i
),t)
∗(−1
)bit
coun
t(i)
h(i)表示i這個二進位制狀態內的起點匹配所需要發生的事件總數。
g(i,t)表示長度為t的序列,每個位置是1~tot的數,有i個數一定要出現,概率是多少。
g的計算當然可以容斥 g(
i,t)
=∑ij
=0cj
i∗(t
ot−j
tot)
t∗(−
1)j
發現f的求和最終變成這個地方對(t
ot−j
tot)
t 的求和。
如果是真分數求和當然很好做。
注意j可以為0,那麼會出現1t
求和,怎麼辦?
只考慮1
t 最終的係數那麼是∑n
−m+1
i=0c
in−m
+1∗(
−1)i
容易發現因為
n>=
m 這個式子的值是0。
如果沒有發現這個,我們還可以換容斥方法。 f(
t)=∑
2n−m
+1−1
i=1g
(h(i
),t)
∗(−1
)bit
coun
t(i)
+1g(i,t)的意義改為,長度為t的序列,每個位置是1~tot的數,有i個數一定不要全部出現,概率是多少。 此時g
(i,t
)=∑i
j=1c
ji∗(
tot−
jtot
)t∗(
−1)j
+1可以發現現在就不帶1t
的項了。
新的式子可以考慮每種情況被計算的次數證明正確性。
回到原來的地方。
然後注意∑t
>=0x
t=11
−x,這個可能涉及求逆元,請進行預處理避免複雜度多帶乙個log。
這個做法的時間複雜度是o(
2n−m
tot)
,只有m較大才能用。
對於m較小的情況,不妨設dp[i,s,k]表示確定到第i個位置,(i-m,i)裡成為起點的二進位制狀態為s,帶權方案數是多少(因為注意最後有-1的係數)。那麼也很好做了,複雜度是o(
2mnt
ot) ,當然因為我好像毛都沒預處理所以我的程式是o(
2mnm
tot)
。
#include
#include
#include
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
#define two(i) (1<<(i))
using
namespace
std;
typedef
long
long ll;
const
int maxn=30+2,mo=998244353;
char s[maxn],h[maxn];
bool dis[maxn][maxn];
int b[maxn][maxn],d[maxn],cnt[maxn*maxn],niy[maxn*maxn];
int c[maxn*maxn][maxn*maxn],f[2][two(15)][maxn*26];
int i,j,k,l,r,t,n,m,now,tot,ni,ans,ca;
bool czy;
int qsm(int x,int y)
bool pd()
return0;}
int calc(int x)
int g(int cnt)
return t;
}void dfs(int x,int f,int y)
dfs(x+1,f,y);
int i,t=0;
bool czy=1;
fo(i,x,x+m-1)
if (!dis[i][s[i-x+1]-'a'])
else
if (czy)
}void brute()
void solve()
d[s[t]-'a']++;
if (d[s[t]-'a']==1) r++;
}l/=2;
}if (!czy) continue;
(f[1-now][j/2][k+r]+=f[now][j][k])%=mo;
if (i+m-1
<=n&&dis[i][s[1]-'a'])
}now=1-now;
}fo(k,0,tot) cnt[k]=0;
fo(j,0,two(m-1)-1)
fo(k,0,tot) (cnt[k]+=f[now][j][k])%=mo;
ans=0;
fo(k,0,tot) (ans+=(ll)cnt[k]*g(k)%mo)%=mo;
(ans+=mo)%=mo;
printf("%d\n",ans);
}int main()
scanf("%s",s+1);
if (!pd())
ni=qsm(tot,mo-2);
fo(i,1,tot) niy[i]=qsm(1-(ll)(tot-i)*ni%mo,mo-2);
c[0][0]=1;
fo(i,1,tot)
if (n-m+1
<=16) brute();
else solve();
}}
合唱隊形 DP
合唱隊形 chorus.pas c cpp n位同學站成一排,老師要請其中的 n k 位同學出列,使得剩下的k位同學排成合唱隊形。合唱隊形是指這樣的一種隊形 設k位同學從左到右依次編號為1,2 k,他們的身高分別為t1,t2,tk,則他們的身高滿足t1 ti 1 tk 1 i k 你的任務是,已知所...
合唱隊形 dp
題目描述 n位同學站成一排,老師要請其中的 n k 位同學出列,使得剩下的k位同學不交換位置就能排成合唱隊形。合唱隊形是指這樣的一種隊形 設k位同學從左到右依次編號為1,2,k,他們的身高分別為t1,t2,tk,則他們的身高滿足t1 t2 ti ti ti 1 tk 1 i k 你的任務是,已知所有...
合唱隊形 NOIP
合唱隊形 noip time limit 1000ms memory limit 65536k description n位同學站成一排,老師要請其中的 n k 位同學出列,使得剩下的k位同學排成合唱隊形。合唱隊形是指這樣的一種隊形 設k位同學從左到右依次編號為1,2 k,他們的身高分別為t1,t2...