CodeForces 285E Positions in Permutations :找出多少恰好满足k个位置的|a[i]-i|==1的n的全排列个数 :dp/思维
dp[i][j] 表示前i个位置中正好有j个位置满足good
对于第i个位置
第i个位置不是good dp[i][j]= dp[i-1][j] 。
第i个位置是good i取i+1转移没问题,但i取i-1可能被前面用过,所以记录后面三个数
根据dp结果可以算出sum[i],然后sum[i] *=fac[N-i],sum[i]就是至少有i个元素是good的排列数,又sum[i] = a[i] + c[i+1][i]*a[i+1] + c[i+2][i]*a[i+2]....,所以可以反解出a[k]
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 using namespace std; 5 #define LL long long 6 #define MOD 1000000007 7 LL cc[1005][1005],fac[1005],sum[1005],x[1005]; 8 LL dp[1005][1005][2][2][2]; 9 int main() 10 { 11 LL i,j,n,k,a,b,c,tmp; 12 for (i=0;i<=1000;i++) 13 { 14 if (i==0) fac[i]=1; 15 else fac[i]=fac[i-1]*i%MOD; 16 cc[i][0]=cc[i][i]=1; 17 for (j=1;j<i;j++) 18 cc[i][j]=(cc[i-1][j-1]+cc[i-1][j])%MOD; 19 } 20 21 scanf("%lld%lld",&n,&k); 22 memset(dp,0,sizeof(dp)); 23 dp[1][0][0][0][0]=1; 24 if (n>1) dp[1][1][0][0][1]=1; 25 for (i=1;i<n;i++) 26 for (j=0;j<=i;j++) 27 for (a=0;a<=1;a++) 28 for (b=0;b<=1;b++) 29 for (c=0;c<=1;c++) 30 { 31 (dp[i+1][j][b][c][0]+=dp[i][j][a][b][c])%=MOD; 32 if (b==0) (dp[i+1][j+1][b][c][0]+=dp[i][j][a][b][c])%=MOD; 33 if (i+2<=n)(dp[i+1][j+1][b][c][1]+=dp[i][j][a][b][c])%=MOD; 34 } 35 36 for (i=0;i<=n;i++) 37 { 38 sum[i]=0; 39 for (a=0;a<=1;a++) 40 for (b=0;b<=1;b++) 41 for (c=0;c<=1;c++) (sum[i]+=dp[n][i][a][b][c])%=MOD; 42 (sum[i]*=fac[n-i])%=MOD; 43 } 44 45 for (i=n;i>=k;i--) 46 { 47 tmp=sum[i]; 48 for (j=i+1;j<=n;j++) 49 tmp=((tmp-cc[j][i]*x[j])%MOD+MOD)%MOD; 50 x[i]=tmp; 51 } 52 printf("%lld\n",x[k]); 53 return 0; 54 }