首页 > 代码库 > hdu4073 Lights

hdu4073 Lights

题意:找出m个不同的n位2进制数,异或值中前v个为1,其余为0的方案数,答案 % 10567201。。

思路:比赛时第一感觉是用容斥原理做的,然后推呀推,搞了2个小时还是错了。。赛后才知道递推才是正解(也许容斥是可以的,是我太弱了,推不出吧)

        因为异或的特性,所以这m个数异或为x(前v个为1,其余为0的m位数),相当于这m个数异或x为0,。。

        也就是说如果知道m-1个数,第m个数也唯一被确定了。。

        假设f[m]为m个数的方案数,那么不考虑重复的情况下,f[m] = C(2^n, m-1)

        那么如何去除重复了,如果出现重复(一定最多只有两个数重复),那么这两个书异或值为0,发现什么了没有。。

        也就是去掉这两个数,就是f[m-2]了吧。。

        除此之外,对于合法的每一组方案,会算m次吧

       so,f[m] = (C(2^n, m-1) - f[m-2] * (2^n - (m-2))) / m;

 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <string> 5 #include <cmath> 6 #include <algorithm> 7 #include <vector> 8 #include <cstdlib> 9 #include <sstream>10 #include <fstream>11 #include <list>12 #include <deque>13 #include <queue>14 #include <stack>15 #include <map>16 #include <set>17 #include <bitset>18 #include <cctype>19 #include <ctime>20 #include <utility>21 #define M0(x) memset(x, 0, sizeof(x))22 #define clr(x,y) memset(x, y, sizeof(x))23 #define P 1056720124 #define N 101025 using namespace std;26 long long c[1010][1010], two[1010];27 int n, m, v;28 long long f[N+5], inv[N+5];  29 using namespace std;30 31 void get_inv(){32     inv[1] = 1;33     for (int i = 2; i < N; ++i)34         inv[i] = (P - P / i) * inv[P % i] % P;35 }36 37 void pre_do(){38      get_inv();39      two[0] = 1;40      for (int i = 1; i < N; ++i){41          two[i] = (two[i-1] << 1);42          if (two[i] >= P) two[i] -= P;43     }44     for (int i = 1; i < N; ++i){45          c[i][0] = 1;46          for (int j = 1; j < N; ++j)47              c[i][j] = c[i][j-1] * (two[i]-j+1) % P * inv[j] % P;    48     }49 }50 51 void solve(){52      if (v == 0) f[0] = 1;53      else f[0] = 0;54      f[1] = 1;55      for (int i = 2; i <= m; ++i){56         long long same = f[i-2] * (two[n]-i+2) % P;57         f[i] = (c[n][i-1] - same) * inv[i] % P;58      }59      f[m] += (f[m] < 0 ? P : 0); 60      printf("%I64d\n", f[m]);61 }62 63 int main(){64 //    freopen("a.in","r",stdin);65 //    freopen("a.out","w",stdout);66     pre_do();67     while (scanf("%d%d%d", &n, &m, &v) != EOF){68          if (!(n+m+v)) break;69          solve();70     }71     return 0;72 }

 

   

 

hdu4073 Lights