P6870 题解

· · 题解

前置芝士:容斥原理

简记为:奇加偶减。

分析:

一道裸的计数 DP 题。

dp_{i,j,k} 为前 i 个人中,已经分配了 j 道题,恰好使 k 个人满足的方案数。

容易发现 dp_{1,0,0}=1

有两组决策,让 i 满足或者不让 i 满足。

$dp_{i+1,j,k} = dp_{i+1,j,k} + dp_{i,j,k}$。 根据容斥原理,最后的答案为,$\sum\limits_{j=1}^n\sum\limits_{k=1}^n (-1)^{k+1} \times dp_{n,j,k}$。 时间复杂度: $O(n^3)$。 空间复杂度:$O(n^3)$。 注意这样会爆空间,应采用滚动数组进行优化。 优化后空间复杂度:$O(n^2)$。 ### 代码: ```cpp #include <bits/stdc++.h> using namespace std; template<typename T>inline void read(register T &x) { register T p = 1,num = 0; char c = getchar(); while(c < '0'||c > '9') { if(c == '-') p = -1; c = getchar(); } while('0' <= c&&c <= '9') { num = (num<<3)+(num<<1)+(c^48); c = getchar(); } x = p * num; } template<typename T>inline void write(register T x) { if(x < 0) putchar('-'),x = -x; if(x > 9) write(x/10); putchar(x%10^48); } #define F(i,a,b) for(register int i=a;i<=b;++i) #define D(i,a,b) for(register int i=b;i>=a;--i) #define ll long long #define N 355 const int mod = 1e9 + 7; int n; ll fac[N],inv[N],pw[N],ans = 0; inline ll qp(ll x,int y) { ll ret = 1; while(y) { if(y & 1) ret = ret * x % mod; x = x * x % mod; y >>= 1; } return ret; } ll dp[2][N][N]; int main() { read(n); inv[0] = inv[1] = fac[0] = fac[1] = pw[0] = 1; F(i,2,n) fac[i] = fac[i-1] * i % mod; F(i,2,n) inv[i] = (mod - mod / i) * inv[mod % i] % mod; F(i,2,n) inv[i] = inv[i] * inv[i-1] % mod; dp[1][0][0] = 1; F(i,1,n) { memset(dp[i+1&1],0,sizeof(dp[i+1&1])); F(j,0,n) F(k,0,n) { if(j+i <= n) dp[i+1&1][j+i][k+1] = (dp[i+1&1][j+i][k+1] + dp[i&1][j][k]*fac[n-j]%mod*inv[n-j-i]%mod*inv[i]) % mod; dp[i+1&1][j][k] = (dp[i+1&1][j][k] + dp[i&1][j][k]) % mod; } } F(j,1,n) F(k,1,n) { dp[n+1&1][j][k] = dp[n+1&1][j][k] * qp(n-k,n-j) % mod; if(k & 1) ans = (ans + dp[n+1&1][j][k]) % mod; else ans = (ans - dp[n+1&1][j][k] + mod) % mod; } write(ans); return 0; } ``` ### 最后 可以发现,输入只有 $n$ 一个数,又是一道打表好题。 ```cpp #include <bits/stdc++.h> using namespace std; int n,ans[]={0,1,3,16,147,1756,25910,453594,9184091,211075288,427652759,380254172,88525330,594308696,594582617,496808516,230533631,930048563,734906046,145824550,963104287,792576272,20842121,926710860,624063170,435324673,941196758,100412345,829823320,16604011,119246612,467453588,296507940,19474275,437566401,580597104,325614134,114081039,16970316,54942632,953074343,664503025,963474561,463988230,901088598,552316694,370315853,363024430,361814615,987969955,356909604,72317551,362905861,844210242,74494960,267374090,9829229,80574666,190779497,993501688,667880842,25921000,891056540,820027654,988133379,860424629,164712123,638551214,64068242,852828384,594849040,713709588,713810843,796807000,639934368,445930895,853650080,686849288,687485088,204732826,938270531,233180167,680119887,798575300,221191668,719754542,183970632,65159363,102009420,106900582,603406815,547850988,69043888,441404069,178108361,171613595,194519530,846734478,733143650,732291535,534460323,424030598,293484626,18815201,585676643,912726223,510270289,151012819,929291571,529049185,117076206,900078971,614777735,348106199,423774249,574430766,526570315,748176803,31818969,501560666,705499512,806457493,862367692,255090341,812275285,136149440,140879753,956968322,984467061,121221372,826702704,995609955,640463338,795423206,438017231,104878010,715195281,87713761,472145514,512444087,528010597,448216404,715864432,365209471,998258892,47038284,945845611,742836670,874752539,351178973,115572999,85498210,750445820,566986136,507422951,263280651,363746668,721379342,657233523,368070024,365517137,557356212,405385770,702731018,726524565,582672271,713823066,172539263,452254713,108837529,685050929,112599223,950160771,537791717,196634339,765215429,723039551,992336331,495498388,734598160,166618212,690246061,613497507,91548173,34919956,30705717,150505766,252695495,997416620,426419436,299460599,841765395,170108584,130185332,573662799,620823933,366877355,870627156,903422770,826307196,361255220,710936088,447319974,885230522,664999650,227183665,35153803,597619983,251027027,953802478,83703267,961654121,351763496,571777475,19373724,564323159,525846126,988983101,113976315,976654852,957177092,547018849,207894228,385473127,401477473,894388178,414921794,285963181,179455247,584525294,721286723,628695619,608638999,599226595,806938357,465644549,296878851,573944747,201107705,585546352,487718852,205357994,277758478,969139685,461220859,461004882,132504633,615131412,824346063,924255686,759290174,358422542,635725603,176609609,917792915,257455569,746184536,316402317,783793186,500434871,517428456,451399654,409643100,482863842,176126614,820640574,657068590,362058002,242650619,186901373,515265982,89328722,942695111,540996271,90622012,138665430,818615553,784975850,417957865,721662199,737792977,495770091,951382091,316267089,374149589,284673490,916782568,790954001,602629711,531192034,664953974,624778690,283568537,34602368,376162450,10239950,812647987,99619518,509861236,256514260,341204270,899013232,614243782,535500022,518807185,472039848,306389369,965790287,155402774,825826404,381603778,307185930,856889200,248603369,192940893,25534731,193328908,438514397,782463496,892910780,686315937,919983254,111131855,299340566,255665989,470190823,983178320,961595576,279565492,63447508,69379637,540261561,887203349,350550553,701031556,754173085,251426123,533498405,443766626,741119012,897485842,708580238,529660266,493526336,813446619,453474512,927471565,937547684,981739148,653129658,688023819}; int main() { scanf("%d",&n); printf("%d",ans[n]); return 0; } ```