码迷,mamicode.com
首页 > 其他好文 > 详细

【CF285E】Positions in Permutations

时间:2019-05-26 17:48:36      阅读:85      评论:0      收藏:0      [点我收藏+]

标签:include   cpp   表示   位置   条件   math   efi   inline   容斥   

题目

刷水题涨信心

显然这是个广义容斥,我们现在算一下至少有\(i\)个完美数的方案数就好了

\(1000\)的数据范围显然在暗示\(n^2\)的dp

我们注意到这个条件大概就是\(P_i=i-1\)\(P_i=i+1\),于是我们可以想象成左右两边各\(n\)个点去完成一个一一匹配

\(dp[i][j][k][p]\)表示左边第\(i\)个数已经匹配完了,一共形成了\(j\)对完美数,\(k\)表示右边对应的第\(i\)个位置的使用状态\(0/1\)\(p\)表示右边第\(i+1\)个数的使用状态

转移显然

代码

#include<cstdio>
#define re register
const int mod=1e9+7;
const int maxn=1005;
int n,m,tot;
int dp[maxn][maxn][2][2],ans[maxn];
int c[maxn][maxn],fac[maxn];
int main() {
    scanf("%d%d",&n,&m);fac[0]=1;
    for(re int i=0;i<=n;i++) c[i][0]=c[i][i]=1;
    for(re int i=1;i<=n;i++) fac[i]=1ll*fac[i-1]*i%mod;
    for(re int i=2;i<=n;i++)
        for(re int j=1;j<i;j++) c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;
    dp[1][0][0][0]=1,dp[1][1][0][1]=1;
    for(re int i=1;i<n;i++)
        for(re int j=0;j<=i;j++)
            for(re int k=0;k<2;k++)
                for(re int p=0;p<2;p++) {
                    if(!dp[i][j][k][p]) continue;
                    dp[i+1][j+1][p][1]=(dp[i+1][j+1][p][1]+dp[i][j][k][p])%mod;
                    if(!k) dp[i+1][j+1][p][0]=(dp[i+1][j+1][p][0]+dp[i][j][k][p])%mod;
                    dp[i+1][j][p][0]=(dp[i+1][j][p][0]+dp[i][j][k][p])%mod;
                }
    for(re int i=0;i<=n;i++)
        ans[i]=(dp[n][i][0][0]+dp[n][i][1][0])%mod;
    for(re int j=m;j<=n;j++) 
        tot=(tot+1ll*((j-m)&1?-1:1)*c[j][m]*fac[n-j]%mod*ans[j]%mod)%mod;
    printf("%d\n",(tot+mod)%mod);
    return 0;
}

【CF285E】Positions in Permutations

标签:include   cpp   表示   位置   条件   math   efi   inline   容斥   

原文地址:https://www.cnblogs.com/asuldb/p/10926580.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!