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 }
View Code

题目链接:http://codeforces.com/problemset/problem/285/E

posted on 2015-03-27 17:54  xiao_xin  阅读(498)  评论(0编辑  收藏  举报

导航