一本通1654車的放置

1654:車的放置

時間限制: 1000 ms         內存限制: 524288 KB

【題目描述】

有下面這樣的一個網格棋盤,a,b,c,d 表示了對應邊長度,也就是對應格子數。php

當 a=b=c=d=2 時,對應下面這樣一個棋盤:c++

要在這個棋盤上放 k 個相互不攻擊的車,也就是這 k 個車沒有兩個車在同一行,也沒有兩個車在同一列,問有多少種方案。一樣只須要輸出答案 mod105+3 後的結果。git

【輸入】

第一行爲有五個非負整數 a,b,c,d 和 kide

【輸出】

包括一個正整數,爲答案 mod105+3 後的結果。spa

【輸入樣例】

2 2 2 2 2

【輸出樣例】

38

【提示】

數據範圍與提示:code

對於所有數據,1a,b,c,d,k1000,且保證了至少有一種可行方案。blog

 

sol:看上去較實際上除了幾個要特判的就沒有了內存

把它看作兩個矩形(當作三個容斥也行,但想到兩個就不會寫這個了吧)get

一個a*b的矩形中,放 i 個方案數就是P(a,i)*C(b,i)或者P(b,i)*C(a,i),input

在下一個(a+c)*d矩形中,放 j 個的方案數就是P(a+c-i,j)*C(d,j)種方案數

O(k)枚舉 i 便可

Ps:在C和P中要注意判斷m和n的大小關係

 

#include <bits/stdc++.h>
using namespace std; typedef long long ll; inline ll read() { ll s=0; bool f=0; char ch=' '; while(!isdigit(ch)) { f|=(ch=='-'); ch=getchar(); } while(isdigit(ch)) { s=(s<<3)+(s<<1)+(ch^48); ch=getchar(); } return (f)?(-s):(s); } #define R(x) x=read() inline void write(ll x) { if(x<0) { putchar('-'); x=-x; } if(x<10) { putchar(x+'0');    return; } write(x/10); putchar((x%10)+'0'); return; } #define W(x) write(x),putchar(' ')
#define Wl(x) write(x),putchar('\n')
const ll Mod=100003; const int N=2005; ll a,b,c,d,k; ll Jiec[N],InvJiec[N]; inline ll Ksm(ll x,ll y) { ll ans=1; while(y) { if(y&1) ans=ans*x%Mod; x=x*x%Mod; y>>=1; } return ans; } inline ll C(ll n,ll m) { if(n<m) return 0; if(!InvJiec[m]) InvJiec[m]=Ksm(Jiec[m],Mod-2); if(!InvJiec[n-m]) InvJiec[n-m]=Ksm(Jiec[n-m],Mod-2); return Jiec[n]*InvJiec[m]%Mod*InvJiec[n-m]%Mod; } inline ll P(ll n,ll m) { if(n<m) return 0; if(!InvJiec[n-m]) InvJiec[n-m]=Ksm(Jiec[n-m],Mod-2); return Jiec[n]*InvJiec[n-m]%Mod; } int main() { ll i,ans=0; R(a); R(b); R(c); R(d); R(k); Jiec[0]=InvJiec[0]=1; for(i=1;i<=max(a+c,b+d);i++) { Jiec[i]=Jiec[i-1]*i%Mod; } for(i=0;i<=k;i++) { ll P1=i,P2=k-i; ll S1=P(a,P1)*C(b,P1)%Mod,S2=P(a+c-P1,P2)*C(d,P2)%Mod; ans+=S1*S2%Mod; ans-=(ans>=Mod)?Mod:0; } Wl(ans); return 0; } /* input 2 2 2 2 2 output 38 input 4 2 2 4 4 output 3144 input 10 10 1 100 10 output 21223 input 555 666 777 888 999 output 94649 */
View Code
相關文章
相關標籤/搜索