zoukankan      html  css  js  c++  java
  • 洛谷P3298 泉

    时空限制 1000ms / 128MB

    题目描述

    作为光荣的济南泉历史研究小组中的一员,铭铭收集了历史上x个不同年份时不同泉区的水流指数,这个指数是一个小于. 2^30的非负整数。第i个年份时六个泉区的泉水流量指数分别为 A(i,l),A(i,2),A(i,3),A(i,4), A(i,5)与 A(i,6)。

    现在铭铭希望知道有多少对不同的年份:i和j,满足这两年恰好有K个泉区的泉水流S指数对应相同。

    输入输出格式

    输入格式:

    第一行有2个整数,分别是N和K

    之后N行,每行有6个整数。第i行的第j个数字A(i,j)表示第i个年份中第j个泉区的泉水流量指数。

    输出格式:

    一个整数表示有多少对不同的年份满足恰有K个区的泉水流量指数对应相同。

    输入输出样例

    输入样例#1: 复制
    3 3
    1 2 3 4 5 6
    1 2 3 0 0 0
    0 0 0 4 5 6
    输出样例#1: 复制
    2

    说明

    对于 100%的数据, 0<=K <=6, 且所有数据中K是等概率出现的, 即对于任意的 0<=x都有大约 1/7 的数据中 K=x. N<=100000


    解:稍加思索,发现我们可以枚举是哪k个相等,但是这样会算重,所以容斥一下。发现26 = 64,有搞头。

    这样问题转化成了给定一个6元组组成的序列,判断其中有多少个相等的。显然只要hash就行了。那么如何对一个6元组hash呢?red sun一语惊醒我:字符串hash啊。

    注意这题容斥的时候要乘组合数,可能只有我没乘组合数还一直以为是hash的锅......

      1 #include <bits/stdc++.h>
      2 
      3 typedef unsigned long long uLL;
      4 typedef long long LL;
      5 const int N = 100010;
      6 const uLL B = 131, MO = 998244353;
      7 
      8 uLL pwB[50], h[N][6], pw2[50], h2[N][6];
      9 int a[N][6], n, k, cnt[70], pw[N];
     10 LL C[10][10];
     11 
     12 inline uLL getHash(int x) {
     13     uLL ans = 0;
     14     for(int i = 0; i < 10; i++) {
     15         ans = ans * B + (x % 10) + '0';
     16         x /= 10;
     17     }
     18     return ans;
     19 }
     20 inline uLL getHash2(int x) {
     21     uLL ans = 0;
     22     for(int i = 0; i < 30; i++) {
     23         ans = (ans * B % MO + (x & 1) + '0') % MO;
     24         x >>= 1;
     25     }
     26     return ans;
     27 }
     28 
     29 namespace Hash {
     30     struct Node {
     31         int cnt, nex;
     32         uLL val, val2;
     33     }node[N]; int tp;
     34     const int mod = 999983;
     35     int e[mod];
     36     inline int insert(uLL v, uLL v2) {
     37         int x = v % mod;
     38         for(int i = e[x]; i; i = node[i].nex) {
     39             if(node[i].val == v && node[i].val2 == v2) {
     40                 return node[i].cnt++;
     41             }
     42         }
     43         node[++tp].val = v;
     44         node[tp].val2 = v2;
     45         node[tp].cnt = 1;
     46         node[tp].nex = e[x];
     47         e[x] = tp;
     48         return 0;
     49     }
     50     inline void clear() {
     51         memset(e, 0, sizeof(e));
     52         tp = 0;
     53         return;
     54     }
     55 }
     56 
     57 int main() {
     58     for(int i = 0; i <= 6; i++) {
     59         C[i][0] = C[i][i] = 1;
     60         for(int j = 1; j < i; j++) {
     61             C[i][j] = C[i - 1][j] + C[i - 1][j - 1];
     62         }
     63     }
     64     scanf("%d%d", &n, &k);
     65     for(int i = 1; i <= n; i++) {
     66         for(int j = 0; j < 6; j++) {
     67             scanf("%d", &a[i][j]);
     68             h[i][j] = getHash(a[i][j]);
     69             h2[i][j] = getHash2(a[i][j]);
     70         }
     71     }
     72 
     73     int lm = (1 << 6);
     74     for(int s = 1; s < lm; s++) {
     75         cnt[s] = 1 + cnt[s - (s & (-s))];
     76     }
     77     pw2[0] = pwB[0] = 1;
     78     for(int i = 0; i < 6; i++) {
     79         pw[1 << i] = i;
     80     }
     81     for(int i = 0; i < 30; i++) {
     82         pwB[i + 1] = pwB[i] * B;
     83         pw2[i + 1] = pw2[i] * B % MO;
     84     }
     85     LL fin = 0;
     86     for(int s = 0; s < lm; s++) {
     87         if(cnt[s] < k) {
     88             continue;
     89         }
     90         LL ans = 0;
     91         Hash::clear();
     92         for(int i = 1; i <= n; i++) {
     93             uLL temp = 0, t2 = 0;
     94             int ss = s;
     95             while(ss) {
     96 
     97                 int t = pw[ss & (-ss)];
     98                 temp = temp * pwB[6] + h[i][t];
     99                 t2 = (t2 * pw2[30] % MO + h2[i][t]) % MO;
    100 
    101                 ss ^= (1 << t);
    102             }
    103             ans += Hash::insert(temp, t2);
    104         }
    105         ans = ans * C[cnt[s]][k];
    106         if((cnt[s] - k) & 1) {
    107             fin -= ans;
    108         }
    109         else {
    110             fin += ans;
    111         }
    112     }
    113 
    114     printf("%lld
    ", fin);
    115     return 0;
    116 }
    AC代码
  • 相关阅读:
    Comparison of MPTCP & CMT-SCTP
    Wireshark
    MPTCP协议相关分析
    抑郁
    MPTCP 源码分析(七) 拥塞控制
    MPTCP 源码分析(六) 数据重发
    MPTCP 源码分析(五) 接收端窗口值
    MPTCP 源码分析(四) 发送和接收数据
    MPTCP 源码分析(三) 子路径选择
    MPTCP 源码分析(二) 建立子路径
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/10821942.html
Copyright © 2011-2022 走看看