题目链接:点击打开链接
题目大意:全错排问题,指定了某些信封装的信的对于编号,求全错排的解~~~~
刚开始拿到这个题目感觉无从下手,无法保存搜索过程的状态,遂找到对应答案相同的解的特点,打表找到了某个稀里糊涂的规律,2333
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long llt;
const int MAXN=1100;
const int MOD=1000000007;
int env[MAXN];
llt dp[MAXN][MAXN];
void init()
{
dp[0][0]=1;dp[1][0]=0;dp[1][1]=0;dp[2][1]=1;
for(int i=2;i<=1000;i++)
dp[i][0]=(dp[i-1][0]+dp[i-2][0])*(i-1)%MOD;
for(int i=4;i<=1000;i+=2) dp[i][i/2]=dp[i-2][(i-2)/2]*(i/2)%MOD;
for(int j=1;j<=500;j++)
for(int i=2*j+1;i<=1000;i++)
dp[i][j]=((i-j)*dp[i-1][j]%MOD+MOD-j*dp[i-3][j-1]%MOD)%MOD;
}
int main()
{
int n;
init();
while(scanf("%d",&n)!=EOF)
{
int ret=0,hook=0;
bool flag=false;
for(int i=1;i<=n;i++)
{
scanf("%d",&env[i]);
if(env[i]) ret++;
if(env[i]==i) flag=true;
}
if(flag)
{
puts("0");
continue;
}
for(int i=1;i<=n;i++)
if(env[env[i]]) hook++;
printf("%d\n",dp[n-hook][ret-hook]);
}
return 0;
}
后面还发现另一种容易理解的解法~~~
#include <cstdio>
#include <cstring>
using namespace std;
int a[1010];
bool f[1010];
__int64 dp[1010][1010];
const __int64 mod=1000000007LL;
__int64 dfs(int,int);
void debug()
{
for(int i=0;i<=9;i++)
{
for(int j=0;j<=i/2;j++)
printf("DP[%d][%d] :%-4d ",i,j,dfs(i,j));
putchar('\n');
}
}
//a个不能放在其原本位置,b个可以放在任意位置
__int64 dfs(int a,int b)
{
if(a<0||b<0)
return 0;
if(dp[a][b]>=0)
return dp[a][b];
__int64 ret;
//如果b的数量为0,就变成了全错排问题
if(b==0) ret=(a-1)*(dfs(a-1,0)+dfs(a-2,0));
//else ret=dfs(a+1,b-1)+dfs(a,b-1);//玄学问题,这个也能过,不过过程不理解
else ret=a*dfs(a-1,b)+b*dfs(a,b-1);
ret%=mod;
return dp[a][b]=ret;
}
int main()
{
int i,n,cnta,cntb;
//freopen("1.in","r",stdin);
//freopen("1.out","w",stdout);
bool flag;
memset(dp,-1,sizeof(dp));
dp[0][0]=1;
debug();
while(scanf("%d",&n)!=EOF)
{
memset(f,0,sizeof(f));
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
cnta=cntb=0;
flag=1;
for(i=1;i<=n;i++)
if(a[i]!=0)
{
if(f[a[i]]==1||a[i]==i) flag=0;
f[a[i]]=1;
}
for(i=1;i<=n;i++)
if(a[i]==0)
{
if(f[i]==0) cnta++;
else cntb++;
}
///cnta表示不能放在其原本位置的信封的个数
///cntb表示可以随意放置的信封数量
if(!flag) printf("0\n");
else printf("%I64d\n",dfs(cnta,cntb));
}
return 0;
}
(最近写题解越来越不走心了,233333333,如果有HUNNU的小伙伴在有生之年能看到我这篇题解,看不懂就直接来问我吧,233333333~~~~~)