[CF285E] Positions in Permutations


https://zybuluo.com/ysner/note/1236806

題面

稱一個\(1-n\)的排列的完美數為有多少個\(i\)滿足\(|P_i−i|=1\)
求有多少個長度為\(n\)的完美數恰好為\(m\)的排列。

  • \(n,m\leq1000\)

解析

因為要計數,所以\(DP\)
顯然狀態中要包含一些信息:統計第\(1-i\)個數的答案、有\(j\)個滿足條件、\(i-1\)\(i+1\)二數是否被用過。
但是如果真這樣設狀態,就只能隔一個數轉移一次(因為得到\(i-1\)的信息必須通過\(i-2\))。
邊界狀態不好設計啊。
然后我懵了

實際上,應該設\(f[i][j][k_{(2)}][l_{(2)}]\)表示在第\(1-i\)個數中,已經填了\(j\)個滿足條件的數,\(k\)表示\(i\)是否已填,\(l\)表示\(i+1\)是否已填。
這樣一切都順理成章了。
決策三種:

  • 這一位先不填數(最后把設定不符合條件的數亂填一下)
  • 這一位填\(i-1\)
  • 這一位填\(i+1\)

這樣\(ans[m]=(dp[n][m][0][0]+dp[n][m][1][0])*2^{n-m}\)(另外兩狀態不合法)

最后考慮計重問題。
這時得到的\(ans[m]\)是完美數\(\geq m\)的所有方案。
\(ans[m]\)包含了\(ans[m+1]\)中的\(C_{m+1}^m\)種方案。
\(ans[m]\)包含了\(ans[m+2]\)中的\(C_{m+2}^m\)種方案。
於是乘上組合數容斥一波即可。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#define re register
#define il inline
#define ll long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define fp(i,a,b) for(re int i=a;i<=b;i++)
#define fq(i,a,b) for(re int i=a;i>=b;i--)
using namespace std;
const int mod=1e9+7,N=6e5+100;
int n,m;
ll dp[1005][1005][2][2],C[1005][1005],ans[1005],jc[1005],anss;
il ll gi()
{
   re ll x=0,t=1;
   re char ch=getchar();
   while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
   if(ch=='-') t=-1,ch=getchar();
   while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
   return x*t;
}
int main()
{
  n=gi();m=gi();
  C[0][0]=1;
  fp(i,1,n)
    {
      C[i][0]=1;
      fp(j,1,i) C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
    }
  jc[0]=1;fp(i,1,n) jc[i]=(jc[i-1]*i)%mod;
  dp[0][0][1][0]=1;
  fp(i,1,n)
    fp(j,0,i)
    fp(k,0,1)
    fp(l,0,1)
    {
      (dp[i][j][l][0]+=dp[i-1][j][k][l])%=mod;//不管
      if(j&&k==0) (dp[i][j][l][0]+=dp[i-1][j-1][k][l])%=mod;//取i-1
      if(j) (dp[i][j][l][1]+=dp[i-1][j-1][k][l])%=mod;//取i+1
    }
  fp(i,0,n) (ans[i]+=dp[n][i][0][0]+dp[n][i][1][0])%=mod,ans[i]=ans[i]*jc[n-i]%mod;
  anss=ans[m];
  re int flag=-1;
  fp(i,m+1,n) anss=(anss+flag*ans[i]*C[i][m]%mod+mod)%mod,flag=-flag;
  printf("%lld\n",anss);
  return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM