3198: [Sdoi2013]spring【容斥原理+hash】

容斥是ans= 至少k位置相等对数C(k,k)-至少k+1位置相等对数C(k+1,k)+至少k+2位置相等对数*C(k+2,k) ……

然后对数的话2^6枚举状态然后用hash表统计即可

至于为什么要乘上一个组合数,详见 https://www.cnblogs.com/candy99/p/6616809.html

我理解的是,因为是枚举状态统计,所以会重复计算C(k+i,k)次

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=100005,mod=2150527;
int n,m,a[N][10],h[N*30],vis[N*30],c[10][10];
struct qwe
{
    int ne,to,sm;
    long long va;
}e[N*30];
long long clc(int s)
{
    long long ans=0,cnt=0;
    for(int i=1;i<=n;i++)
    {
        long long tmp=0;
        int j,k;
        for(j=1;j<=6;j++)
            if(s&(1<<(j-1)))
                tmp=tmp*1000003+a[i][j];
        j=(tmp%mod+mod)%mod;
        if(vis[j]!=s)
        {
            vis[j]=s;
            h[j]=0;
        }
        for(k=h[j];k;k=e[k].ne)
            if(e[k].va==tmp)
            {
                ans+=e[k].sm;
                e[k].sm++;
                break;
            }
        if(!k)
        {
            cnt++;
            e[cnt].va=tmp;
            e[cnt].sm=1;
            e[cnt].ne=h[j];
            h[j]=cnt;
        }
    }
    return ans;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=6;j++)
            scanf("%d",&a[i][j]);
    c[0][0]=1;
    for(int i=1;i<=6;i++)
    {
        c[i][0]=1;
        for(int j=1;j<=i;j++)
            c[i][j]=c[i-1][j-1]+c[i-1][j];
    }
    long long ans=0;
    for(int i=0;i<64;i++)
    {
        int cnt=0;
        for(int j=0;j<6;j++)
            if(i&(1<<j))
                cnt++;
        if(cnt<m)
            continue;
        ans+=(((cnt-m)&1)?-1:1)*clc(i)*c[cnt][m];
    }
    printf("%lld\n",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/lokiii/p/9614282.html

时间: 2024-08-29 14:08:45

3198: [Sdoi2013]spring【容斥原理+hash】的相关文章

bzoj 3198: [Sdoi2013]spring 题解

[原题] 3198: [Sdoi2013]spring Time Limit: 40 Sec  Memory Limit: 256 MB Submit: 253  Solved: 95 Description Input Output Sample Input 3 3 1 2 3 4 5 6 1 2 3 0 0 0 0 0 0 4 5 6 Sample Output 2 HINT [题解]这道题明明是水题,坑了我两天!!!真是伤心.发现哈希都不熟练了. 首先很容易想到是2^6枚举01状态,使得1

BZOJ 3198 Sdoi2013 spring Hash+容斥原理

题目大意:给定n个元素,每个元素是一个六元组,求有多少对元素满足相同的位置恰好有k个 首先对于恰好有K个这种东西果断考虑容斥原理 我们2^6枚举相同的位置 恰好有k个元素相同的对数=至少有k个位置相同的对数-至少有k+1个位置相同的对数+至少有k+2个位置相同的对数-- 但是我们计数时会发现一些问题 比如下面这组样例显然是0: 2 3 1 2 3 4 5 5 1 2 3 4 6 6 但是这一对元素被加了C(4,3)次,只被减掉了C(4,4)次 因此我们将公式改成这样: 恰好有k个元素相同的对数=

[BZOJ 3198] [Sdoi2013] spring 【容斥 + Hash】

题目链接:BZOJ - 3198 题目分析 题目要求求出有多少对泉有恰好 k 个值相等. 我们用容斥来做. 枚举 2^6 种状态,某一位是 1 表示这一位相同,那么假设 1 的个数为 x . 答案就是 sigma((-1)^(x - k) * AnsNow * C(x, k)) .注意 x 要大于等于 k. 对于一种状态,比如 10110,就是要保证第 1, 3, 4 个值相同. 这些值相同的对数怎么来求呢?使用Hash. 将这些位上的值 Hash 成一个数,然后枚举  [1, i] , 每次求

BZOJ 3198 SDOI2013 spring

为什么SDOI省选一年考两次容斥原理? 我们很容易发现>=k个相等时很好计算的 但是我们要求恰好k个,那么我们容斥即可 至于计算>=k个相等,首先我们枚举相等位置,对每个串对应位置做一遍hash就可以了 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<cstdlib> using namespace std; type

BZOJ3198 SDOI2013 spring HASH+容斥原理

题意:给定6个长度为n的数列,求有多少个数对(i,j)((i,j)≡(j,i))使得i和j位置恰好有K个数相同,其中0≤K≤6 题解: 设fi=至少有K个数相同的位置对的数量,用2^6枚举每一种可能,根据容斥原理,答案就是\[\sum\limits_{i = K}^N {{f_i}C_i^K{{\left( { - 1} \right)}^{i - K}}} \] 至于多乘一个组合数,是因为当前枚举到有x个数相同,一个位置对有i个相同的数,那么累计的时候就会算成$C_x^i$,因此实际上这个位置

bzoj3198: [Sdoi2013]spring

Description Input Output 容斥并用hash判断.保存状态,类似bzoj2012 #include<cstdio> int read(){ int x=0,c=getchar(); while(c>57||c<48)c=getchar(); while(c>47&&c<58)x=x*10+c-48,c=getchar(); return x; } int n,k; int w[64],x[6],x0[6]; int K[][7]={

bzoj 3197 [Sdoi2013]assassin(Hash+DP+KM)

Description Input Output Sample Input 4 1 2 2 3 3 4 0 0 1 1 1 0 0 0 Sample Output 1 HINT [思路] Hash,DP,KM 树的形态可以有多种但是他的中心只有一个.先找出中心,如果在边上则新建一个节点.以中心为根建树,同时求出Hash.Hash函数如下: H[u]=((((A*H[son1])*p+H[son2])*p+H[son3])*p) 通过判断hash值和节点深度dep就可直到是否同构. 在树上进行DP

bzoj3198【SDOI2013】spring

3198: [Sdoi2013]spring Time Limit: 40 Sec  Memory Limit: 256 MB Submit: 725  Solved: 216 [Submit][Status][Discuss] Description Input Output Sample Input 3 3 1 2 3 4 5 6 1 2 3 0 0 0 0 0 0 4 5 6 Sample Output 2 HINT Dragonite修正数据 Source Hash 容斥原理+哈希 枚举

计数类问题专题

主要是前两天被uoj的毛爷爷的题虐的不轻,心里很不爽啊,必须努力了,, 计数类问题分为:1.组合数学及数论计数 2.dp:状态压缩dp,插头轮廓线dp,树形dp,数位dp,普通dp 3.容斥原理 4.polya原理 5.图论计数 6.生成函数 7.其它(生成树计数等等) 本文主要研究前3个内容 考虑基本计数原理:加法原理,减法原理,乘法原理,除法原理 计数的基本原则:结果不重不漏 加法原理比较自然,中间过程有时减法原理 考虑到无向,有向图的各种量值(生成树之类)计数,状态压缩dp解决 论文:ht