給出n個數,每個數是0或1.
再給出m個限制,每個限制(x,y)表示「前x個數中有y個1」或「後y個數中有x個1」
求這樣的序列的個數。
n<=5000,m<=1000
再一次被uer給虐了。
其實這道題劼鏼爺已經講的很清楚了。(撲通撲通跪下來)
當x!=y的時候,很顯然已經確定這個限制是限制字首還是字尾的。
當x=y的時候,我們只需要保留最大的那個x就行了。(顯然)
然後,我們可以用容斥。
答案是x=y是字首限制的個數+字尾限制的個數-前字尾都限制的個數。
那麼,現在就是有一堆前字尾的限制,讓你求方案數。
如果只有前(後)綴,那麼,就相當於把這n個數劃分成了m個區間,對於每乙個區間單獨限制。一堆組合數乘起來就好了。
那麼,前字尾都有的話,我們就可以把字尾轉化成字首。(反之亦然)
列舉1的總和就行了。
劼鏼**好!(刷隊形)
#include
#include
#include
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define n 5005
using namespace std;
typedef long long ll;
const int mo=998244353;
struct notea[n],p[n];
bool cmp(note x,note y)
int c[n][n],n,m,ty,x,y,z,ans,tot;
int main()
for(scanf("%d",&ty);ty;ty--)
a[++tot].x=z;a[tot].y=z;a[tot].bz=0;a[tot].ty=1;
a[++tot].x=n-z;a[tot].y=z;a[tot].bz=1;a[tot].ty=2;
sort(a+1,a+tot+1,cmp);
fo(type,1,3)
fo(i,1,n)
if (p[cnt].x
y) if (p[cnt].x-p[cnt-1].x
y-p[cnt-1].y)
if (p[cnt].y-p[cnt-1].y
<0)
}if (pd) continue;int sum=1;
fo(j,1,cnt) sum=(ll)sum*c[p[j].x-p[j-1].x][p[j].y-p[j-1].y]%mo;
sum=(ll)sum*c[n-p[cnt].x][i-p[cnt].y]%mo;
if (type<=2) ans=(ans+sum)%mo;
else ans=(ans-sum+mo)%mo;
}printf("%d\n",(ans%mo+mo)%mo);
}}
UOJ 209 UER 6 票數統計
原題鏈結 妹滋滋是乙個善於程式設計的女孩子。但是某一天,她一不小心把 uoj 後台的票數統計程式寫錯了。本來嘛在這種根本沒有什麼用的功能上出了 bug 也沒有什麼大關係,但是又有某一天,uoj 突然就開始搞全民公投了。這可怎麼辦呢?如果這個訊息讓別人知道的話自己肯定會被查表,更不要說讓所有使用者重新...
UOJ 210 UER 6 尋找罪犯
有n個人分為好人和壞人,說了m句話。好人不會說假話,壞人至多說一句謊話。求出一組解,滿足要求。利用2 sat拆點,乙個人拆成兩個點,表示他是好人和壞人。然而這樣的話邊數是m 2的,所以用前 字尾和優化構圖即可。1 include 2 using namespace std 34 const int ...
uoj140 UER 4 被粉碎的數字
題目 看起來就像是數字 rm dp 不妨從豎式乘法的角度來考慮這個問題 為了方便處理進製,我們得從低位向高位填數 設 dp i 0 1 j p t 表示填到了第 i 位,卡不卡上界,f x j f k times x p 不計算最高位 需要向最高位進 t 的 x 有多少個 這裡的卡上界比較奇怪,如果...