BZOJ 4498 魔法的碰撞

2021-08-02 13:05:20 字數 1367 閱讀 3173

魔法總是令戰鬥的局面變幻莫測。

然而魔力的碰撞則更是天馬行空,甚至會出現無法控制而自取滅亡的情況。

因此,魔力碰撞總是沒有辦法的辦法。

設想有一條長度為l的戰線,你可以把你的魔法師們安排在戰線上的每個格仔。每乙個魔法師都有乙個攻擊範圍di,排兵時必須保證任意兩個魔法師的攻擊範圍的較大值小於等於它們之間的距離(距離即為它們座標的差值)。為了更好地迷惑敵人,你須要求出總共有多少種布陣的方案。

第一行兩個整數l,n,n代表魔法師個數。

第二行n個數,描述魔法師的攻擊範圍di。

n≤40,di≤40,l≤1000000

一行,乙個整數,代表方案數mod 1000000007的值。

9 31 2 4

42~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

組合數問題+dp+思路~

我們記a[i]=d[i]-1,方便計算組合數。

我們把所有魔法師都堆在一邊,使得兩兩之間的距離都是最小的,假設此時魔法師的總長度是x,我們把剩餘的空位都放在魔法師中間,這樣,固定順序的魔法師鏈總共有c(l-x,n)種擺放方式。

但是我們顯然不能直接列舉魔法師的順序。

所以我們把魔法師排序,然後從大到小放入序列中,這樣,如果魔法師身邊有乙個空位,就能給總的最小距離貢獻a[i],如果沒有空位,則這位魔法師的距離就已經被前面放入的魔法師覆蓋了。這樣,每位魔法師放入後都有三種情況:有左右兩個空位(空位+1,距離+2*a[i]),有左或右乙個空位(空位不變,距離+a[i];注意這裡有左右兩種情況,答案*2),左右都沒有空位(空位-1,距離不變)。

所以我們用f[i][j][k]表示放入第i位魔法師,放入後有j個空位,目前總距離為k時的方案數,那麼直接用前面提到的三種情況更新即可。

初始化的時候sheng[0]=ni[0]=1!

#include#include#include#includeusing namespace std;

#define mod 1000000007

#define ll long long

int n,l,a[41],sheng[1000001],ni[1000001],f[2][42][3201],kkz,now,ans;

int read()

while(ch>='0' && ch<='9')

return x*f;

}int mi(int u,int v)

int c(int n,int m)

} for(int i=0;i<=2*now;i++) ans=(ans+((ll)f[kkz][0][i]*c(l-i,n)%mod))%mod;

printf("%d\n",ans);

return 0;

}

BZOJ4498 魔法的碰撞 DP

我們先考慮全部緊湊的情況,也就是沒有多餘的空格的情況 將d id i di 先不考慮魔法師佔的空間 這裡用了乙個很巧妙的方法,多加一維,表示預留的空位。加入a會有三種情況 e表示空位 a,ae或ea,eae。對於第一種,表示a兩邊都有魔法師。對於第二種,表示a的一邊有,一邊沒有。對於第三種,表示a的...

BZOJ4498 魔法的碰撞(動態規劃)

點此看題面 大致題意 你要在 m 個格仔中擺放 n 個魔法師 每個魔法師有乙個攻擊範圍 使他們不能互相攻擊,求方案數。要用魔法戰勝魔法!顯然我不會魔法只會膜法,所以就被這道題吊錘了 這是一道比較有趣的題。題意看起來很簡單,資料範圍好像也很小,於是我就先後飛快地有了兩個想法,然後又先後飛快地hack掉...

BZOJ4498 魔法的碰撞(組合數學 dp)

傳送門 首先我們發現乙個排列,2個魔法使之間一定要填max di,di 1 1max d i,d 1 max di di 1 1個格仔而如果總共一定要填的為k kk個,貢獻就是 l kn n l k 考慮dpdp dp出每種情況的方案數 首先按d dd從大到小排序消除max maxma x我們發現乙...