1. 程式人生 > >【FCS NOI2018】福建省冬摸魚筆記 day2

【FCS NOI2018】福建省冬摸魚筆記 day2

++ line rac tar return 講師 efi 沒有 ram

第二天。

同學還是不帶本子記筆記。dalao。

第二天:圖論,講師:@ExfJoe

全程劃水,前面都講水算法【雖然我可能已經忘記了】什麽最短路,Tarjan,最小生成樹,2SAT,差分約束啥的,我現在肯定寫不出來啦。

後面題目也還挺好,可能是聽的比較懂的一天吧。不過也很有挑戰性。


中午劃水


還以為下午的題目會和上午有關系,事實證明我想太多。

T1想了個錯誤分塊,寫了n久掛了,不想調,正解主席樹。

T2簡單數學題,瞎推式子就完了,後悔沒有去做啊。

T3毒瘤模擬題,什麽切比雪夫,什麽曼哈頓,什麽奇偶分開,反正不想做。

爆零選手很難受。

【T2】

題面:對兩個排列定義函數\(F(P_1,P_2)=\sum_{l=1}^{n}\sum_{r=l}^{n}f_{E}(P_1[l\cdots r],P_2[l\cdots r])\)。而\(f_{E}(a,b)\)表示\(a,b\)離散後順序是否一樣,且\(a,b\)的逆序對數是否不超過\(E\),例如\(f_{1}([2,1,3],[6,3,8])=1\),\(f_{30}([2,1,3],[3,2,1])=0\),\(f_{0}([1,3,2],[1,3,2])=0\)。

求出當\(P_1,P_2\)取遍所有\(1\sim n\)的全排列時,\(F(P_1,P_2)\)的和。

題解:分開考慮每一個\([l\cdots r]\)的貢獻,瞎推式子瞎計算,得到答案:\(\sum_{i=1}^{n}(n-i+1)f(i,E)(\frac{n!}{i!})^2\),\(f(i,j)\)表示長度為\(i\),逆序對數不超過\(j\)的全排列數量。

\(f(i,j)\)可以\(O(n^3)\)預處理DP。這題就做完了。

技術分享圖片
 1 #include<cstdio>
 2 #define Mod 1000000007
 3 int n,E;
 4 int f[501][124751];
5 int fra[501],inv[501]; 6 inline int Min(int x,int y){return x<y?x:y;} 7 inline int Mo(int x){return x>=Mod?x-Mod:(x<-Mod?x+(Mod<<1):(x<0?x+Mod:x));} 8 void init(){ 9 f[1][0]=1; 10 for(int i=2,s,t;i<=500;++i){ 11 f[i][0]=1; s=i*(i-1)/2; t=(i-1)*(i-2)/2; 12 for
(int j=1;j<=s;++j) 13 f[i][j]=Mo(f[i][j-1]+(j<=t?f[i-1][j]:f[i-1][t])-(j>=i?f[i-1][j-i]:0)); 14 } 15 fra[1]=inv[1]=1; 16 for(int i=2;i<=500;++i) fra[i]=1ll*fra[i-1]*i%Mod; 17 for(int i=2;i<=500;++i) fra[i]=1ll*fra[i]*fra[i]%Mod; 18 for(int i=2;i<=500;++i) inv[i]=1ll*(Mod-Mod/i)*inv[Mod%i]%Mod; 19 for(int i=2;i<=500;++i) inv[i]=1ll*inv[i-1]*inv[i]%Mod; 20 for(int i=2;i<=500;++i) inv[i]=1ll*inv[i]*inv[i]%Mod; 21 } 22 int main(){ 23 freopen("perm.in","r",stdin); 24 freopen("perm.out","w",stdout); 25 init(); 26 int T; scanf("%d",&T); 27 while(T--){ 28 scanf("%d%d",&n,&E); 29 long long ans=0; 30 for(int i=1;i<=n;++i) 31 ans=Mo(ans+1ll*(n-i+1)*inv[i]%Mod*f[i][Min(E,i*(i-1)/2)]%Mod); 32 ans=1ll*ans*fra[n]%Mod; 33 printf("%d\n",ans); 34 } 35 return 0; 36 }
View Code

【FCS NOI2018】福建省冬摸魚筆記 day2