HDU 3664 Permutation Counting(DP)
弱爆啦,组合弱爆了,反正是没想出来怎么搞这个题,其实这个公式不难推啊,反正就是没推出来。今天队内赛,实在是没办法了,暴力写了个DFS,先把10以内的打出表来,发现类似杨辉三角的一个表,推不出公式,只能找规律了。也推公式,也找规律,中间还走会了神,发现borad上过的人N多了,有些着急,这样应该不难吧。。。又推了会,还是没想出来,找规律吧,估摸着应该是和上两项有关系,自己写了小程序测试一下几个数据和scf讨论了下,貌似真的是找出规律了。。。然后时间不多了,好在代码很短,马上快结束了,乱写了,最后在各种乱搞+思考之下,和暴力的写的数据对上了,中间错了2次,好在在4:53的时候终于AC了。。。。
公式的意义:p[i][j] = (i-j)*p[i-1][j-1] + (j+1)*p[i-1][j];对最后一个数进行讨论,最后一个数字,如果和a[i] > i的位置交换,最后一个数一定比那个位置大,所以之前就必须有j个a[i] > i的数,所以方案数为(j+1)*p[i-1][j] +1代表最后一个数的位置,如果最后一个数和a[i] < i的位置交换共有(i-1) - (j-1)个 ,则方案数为(i-j)*p[i-1][j-1]。
1 #include <cstdio> 2 #include <cstring> 3 using namespace std; 4 #define MOD 1000000007 5 __int64 p[1001][1001]; 6 int main() 7 { 8 int i,j,n,k; 9 for(i = 1;i <= 1000;i ++) 10 { 11 p[i][0] = 1; 12 p[i][i-1] = 1; 13 } 14 for(i = 3;i <= 1000;i ++) 15 { 16 for(j = 1;j <= (i+1)/2-1;j ++) 17 { 18 p[i][i-1-j] = p[i][j] = (((i-j)*p[i-1][j-1])%MOD+((j+1)*p[i-1][j])%MOD)%MOD; 19 } 20 } 21 while(scanf("%d%d",&n,&k)!=EOF) 22 { 23 printf("%I64d\n",p[n][k]); 24 } 25 return 0; 26 }