team2012-F3-sol-0002

从 Trac 迁移的文章

这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。

原文章内容如下:

{{{
题意:长度为n的全排列,其中给定几个位置的约束(不能放某个数),求合法方案数。
解法:用容斥原理,全部方案数n! - 违反一个约束的方案数 + 违反两个约束的方案数 - ... 
其中违反k个约束的方案数即 (从m个约束中选出k个互不影响的约束) * (n-k)!
前面一项可用dfs搜出,复杂度2^m
另外出数据的时候貌似有重复的约束-_-#判一下重复就好了
}}}
{{{
#include <iostream>
#include <vector>
#include <cstring>

using namespace std;

typedef long long LL;

const int MOD = 55566677;
LL ans, f[60];
int has[60], n, m, rep[60][60];
vector<int> fbd[60];

void dfs(int dp, int cnt)
{
    if(dp == n+1)
    {
        if(cnt&1)
        {
            ans -= f[n-cnt];
            if(ans < 0)
                ans += MOD;
        }
        else
        {
            ans += f[n-cnt];
            ans %= MOD;
        }
        return;
    }
    dfs(dp+1, cnt);
    for(int i=0;i<fbd[dp].size();i++)
    {
        int v = fbd[dp][i];
        if(!has[v])
        {
            has[v] = 1;
            dfs(dp+1, cnt+1);
            has[v] = 0;
        }
    }

}

int main()
{
    f[0] = 1;
    for(int i=1;i<=50;i++)
        f[i] = (f[i-1]*i) % MOD;
    while(cin>>n>>m)
    {
        memset(rep, 0, sizeof(rep));
        for(int i=1;i<=n;i++)
            fbd[i].clear();
        for(int i=1;i<=m;i++)
        {
            int a, b;
            cin>>a>>b;
            if(!rep[a][b])
                fbd[a].push_back(b);
            rep[a][b] = 1;
        }
        ans = 0;
        memset(has, 0, sizeof(has));
        dfs(1, 0);
        cout<<ans<<endl;
    }
    return 0;
}
}}}
题意:长度为n的全排列,其中给定几个位置的约束(不能放某个数),求合法方案数。
解法:用容斥原理,全部方案数n! - 违反一个约束的方案数 + 违反两个约束的方案数 - ... 
其中违反k个约束的方案数即 (从m个约束中选出k个互不影响的约束) * (n-k)!
前面一项可用dfs搜出,复杂度2^m
另外出数据的时候貌似有重复的约束-_-#判一下重复就好了
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
typedef long long LL;
const int MOD = 55566677;
LL ans, f[60];
int has[60], n, m, rep[60][60];
vector<int> fbd[60];
void dfs(int dp, int cnt)
{
    if(dp == n+1)
    {
        if(cnt&1)
        {
            ans -= f[n-cnt];
            if(ans < 0)
                ans += MOD;
        }
        else
        {
            ans += f[n-cnt];
            ans %= MOD;
        }
        return;
    }
    dfs(dp+1, cnt);
    for(int i=0;i<fbd[dp].size();i++)
    {
        int v = fbd[dp][i];
        if(!has[v])
        {
            has[v] = 1;
            dfs(dp+1, cnt+1);
            has[v] = 0;
        }
    }
}
int main()
{
    f[0] = 1;
    for(int i=1;i<=50;i++)
        f[i] = (f[i-1]*i) % MOD;
    while(cin>>n>>m)
    {
        memset(rep, 0, sizeof(rep));
        for(int i=1;i<=n;i++)
            fbd[i].clear();
        for(int i=1;i<=m;i++)
        {
            int a, b;
            cin>>a>>b;
            if(!rep[a][b])
                fbd[a].push_back(b);
            rep[a][b] = 1;
        }
        ans = 0;
        memset(has, 0, sizeof(has));
        dfs(1, 0);
        cout<<ans<<endl;
    }
    return 0;
}