zoukankan      html  css  js  c++  java
  • 【poj3875】 Lights

    http://poj.org/problem?id=3875 (题目链接)

    题意

      有M个N位的不同的二进制数,他们异或起来前v位等于1,求这m个数的不同组合方式(同一组数不同顺序不算)。

    Solution

      如果任意两个数可以相同就非常好做了,然而。。事实总是那么令人悲伤。

      考虑dp。假设最后异或出来的数为${V}$,令${f_m}$表示m个数的不同方案(这里我们先求解不同顺序算不同方案的,更好处理一些)。那么如果我们先选出其中${m-1}$个数,它的方案就是:

    $${(m-1)!×C_{2^n}^{m-1}}$$

      这很好理解,一共有${2^n}$个数可供选择,从中任意选取${m-1}$个数,令其为${a_1,a_2,a_3······a_{m-1}}$那么剩下的第${a_m}$个数就可以确定了:

    $${ecause a_1~XOR~a_2~XOR······XOR~a_m=V}$$

    $${ herefore a_m=V~XOR~a_1~XOR~a_2~XOR······XOR~a_{m-1}}$$

      然而问题来了,如果${a_m}$求出来与之前已经选择好了的${m-1}$个数中的某一个相等怎么办?

      假设${a_m=a_1}$,因为相同的数异或起来等于0,则有:

    $${a_2~XOR~a_3~XOR······XOR~a_{m-1}=V}$$

      这个式子的方案数代表什么,不就是代表${f_{m-2}}$吗。所以我们可以列出dp方程:

    $${f_m=(m-1)!×C_{2^n}^{m-1}-(m-1)×(2^n-(m-2))×f_{m-2}}$$

      其中第一项${(m-1)!×C_{2^n}^{m-1}}$很好理解,就是不考虑${a_m}$与之前已经选好的数相同的方案数。

      第二项中${(m-1)}$表示${a_m}$可以与${m-1}$个数中的任意一个相同,${(2^n-(m-2))}$表示${a_m}$的值的选择方案。

      这里还要注意一个地方:${C_{2^n}^{m-1}}$怎么求。考虑Lucas定理求解组合数取模:

    $${Lucas(n,m)=C_{n~mod~p}^{m~mod~p}*Lucas(n/p,m/p)}$$

      因为m最大为1000,恒小于模数p,所以${Lucas(n/p,m/p)=1}$,所以:

    $${C_{2^n}^{m-1}=C_{2^{n}~mod~p}^{m~mod~p}}$$

    $${ans=frac{f[m]}{m!}}$$

    细节

      此时,问题已经得到了解决。什么?你说过不了样例?

      嘿嘿嘿,→_→。

      显然${f[0]=0,f[1]=1}$,那么${f[2]=?}$。

      考虑${v=0}$的情况,因为两个数不能相同,而只有相同的两个数的异或和等于0,所以${f[2]=0}$。

      而当${v>0}$时,${f[2]=C_{2^n}^{1}}$。

      此时,问题已经得到了解决(真的)

    代码

    // poj3875
    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #define LL long long
    #define inf 2147483640
    #define MOD 10567201
    #define Pi acos(-1,0)
    #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
    using namespace std;
    
    const int maxn=2000;
    LL f[maxn],fac[maxn],C[maxn];
    int n,m,v;
    
    LL power(LL a,LL b) {
    	LL res=1;
    	while (b) {
    		if (b&1) res=res*a%MOD;
    		b>>=1;a=a*a%MOD;
    	}
    	return res;
    }
    int main() {
    	fac[0]=1;for (int i=1;i<=1000;i++) fac[i]=fac[i-1]*i%MOD;
    	while (scanf("%d%d%d",&n,&m,&v)!=EOF) {
    		if (!n && !m && !v) break;
    		LL tmp=power(2,n);
    		C[0]=1;
    		for (int i=1;i<=m;i++) {
    			int inv=power(i,MOD-2);
    			C[i]=C[i-1]*(tmp-i+1)%MOD*inv%MOD;
    		}
    		f[1]=1;f[0]=0;if (v==0) f[2]=0;else f[2]=tmp;
    		for (int i=3;i<=m;i++) {
    			f[i]=(fac[i-1]*C[i-1]%MOD-(i-1)*(tmp-(i-2))%MOD*f[i-2]%MOD+MOD)%MOD;
    		}
    		LL inv=power(fac[m],MOD-2);
    		printf("%lld
    ",inv*f[m]%MOD);
    	}
        return 0;
    }
    

      

  • 相关阅读:
    IKAnalyzer
    stanford corenlp的TokensRegex
    Linux网络编程-tcp缓存设置
    Java NIO(2):缓冲区基础
    Java NIO(1):迟迟登场的NIO
    git的笔记和使用中的一些技巧的总结
    vagrant 系列 博客
    flutter创建swift kotlin项目
    react eject 命令失败
    react native react-native-vector-icons/Ionicons 出现 Unrecognized font family的错误
  • 原文地址:https://www.cnblogs.com/MashiroSky/p/6235007.html
Copyright © 2011-2022 走看看