prow2012-A3-0002

从 Trac 迁移的文章

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

原文章内容如下:

题意:n元置换{A i},满足m个A bi!=c i , 1<=bi , ci<=n, i=1..m,计算这样的置换的数量。(zYc学长那copy题意最省时间什么的>.<)

很容易想到的是1<<25的容斥,但是太大了,比赛时不敢写,没想到标程还真是……

枚举2进制取舍是完整的1<<25,用DFS进行取舍可以在发生冲突的第一时间return,

{{{
#include <vector>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <set>
#include <map>
#include <sstream>
#include <string>
#include <math.h>
using namespace std;
bool use[2][60];
int limit[60][2],N,M,MOD =55566677 ;
long long A[60],ans;
void dfs(int now,int k){
    if (now==M){
        if (k&1) ans-=A[N-k],ans%=MOD;
        else ans+=A[N-k],ans%=MOD;
        return ;
    }
    bool &one = use[0][limit[now][0]];
    bool &two = use[1][limit[now][1]];
    if (!one&&!two){
        one = two = true;
        dfs(now+1,k+1);
        one = two = false;
    }
    dfs(now+1,k);
}

int main(){
    A[0] = 1;
    int i,a,b,j;
    for (i=1;i<=50;i++)
        A[i] = A[i-1]*i,A[i]%=MOD;

    while(scanf("%d%d",&N,&M)!=EOF){
        ans = 0;
        memset(use,false,sizeof(use));
        int T = 0;
        for (i=0;i<M;i++){
            scanf("%d%d",&a,&b);
            a--,b--;
            for (j=0;j<i;j++)
                if (a==limit[j][0]&&b==limit[j][1])
                    break;
            if (j>=i)
            limit[T][0] = a,limit[T][1] = b,T++;
        }
        M = T;
        dfs(0,0);
        ans = (ans%MOD+MOD)%MOD;
        printf("%lld\n",ans);
    }
}

}}}

题意:n元置换{A i},满足m个A bi!=c i , 1<=bi , ci<=n, i=1..m,计算这样的置换的数量。(zYc学长那copy题意最省时间什么的>.<)

很容易想到的是1<<25的容斥,但是太大了,比赛时不敢写,没想到标程还真是……

枚举2进制取舍是完整的1<<25,用DFS进行取舍可以在发生冲突的第一时间return,

#include <vector>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <set>
#include <map>
#include <sstream>
#include <string>
#include <math.h>
using namespace std;
bool use[2][60];
int limit[60][2],N,M,MOD =55566677 ;
long long A[60],ans;
void dfs(int now,int k){
    if (now==M){
        if (k&1) ans-=A[N-k],ans%=MOD;
        else ans+=A[N-k],ans%=MOD;
        return ;
    }
    bool &one = use[0][limit[now][0]];
    bool &two = use[1][limit[now][1]];
    if (!one&&!two){
        one = two = true;
        dfs(now+1,k+1);
        one = two = false;
    }
    dfs(now+1,k);
}
int main(){
    A[0] = 1;
    int i,a,b,j;
    for (i=1;i<=50;i++)
        A[i] = A[i-1]*i,A[i]%=MOD;
    while(scanf("%d%d",&N,&M)!=EOF){
        ans = 0;
        memset(use,false,sizeof(use));
        int T = 0;
        for (i=0;i<M;i++){
            scanf("%d%d",&a,&b);
            a--,b--;
            for (j=0;j<i;j++)
                if (a==limit[j][0]&&b==limit[j][1])
                    break;
            if (j>=i)
            limit[T][0] = a,limit[T][1] = b,T++;
        }
        M = T;
        dfs(0,0);
        ans = (ans%MOD+MOD)%MOD;
        printf("%lld\n",ans);
    }
}