首先这个aia_iai​相同的时候无序的要求,直接按有序求答案,然后除aia_iai​相同的个数的阶乘即可,因为我们的bbb两两不同。
有序的答案要两两不同,我们考虑容斥哪些相同,可以想到的较高效容斥是枚举将mmm个数划分为若干个集合(有Bell(m)Bell(m)Bell(m)种方案),每个集合中的数字都相等。
但是容斥系数不太好找,因为一般的集合划分容斥是不同集合间的一定(不)满足条件,而这个是集合之间的一定(不)满足条件。
考虑我们用经典容斥的观点给每个集合一个容斥系数,使得一个划分方案的容斥系数等于集合的容斥系数之积。
那么考虑一个容斥系数f(x)=∑i=1fixii!f(x)=\sum_{i=1} \frac {f_ix^i}{i!}f(x)=∑i=1​i!fi​xi​,其中fif_ifi​是iii个点的集合的容斥系数,满足ef(x)=xe^{f(x)}=xef(x)=x。
根据expexpexp的组合意义,
[n=1]=[xn]ef(x)=fn+∑i=1n−1(n−1i−1)fi[xn−i]ef(x)[n=1]=[x^n]e^{f(x)}=f_n+\sum_{i=1}^{n-1} \binom{n-1}{i-1} f_i [x^{ n-i}]e^{f(x)}[n=1]=[xn]ef(x)=fn​+∑i=1n−1​(i−1n−1​)fi​[xn−i]ef(x)
后面的∑\sum∑是求111号点所在的集合有哪些点,然后根据定义。
所以fi=(−1)i−1(i−1)!f_{i} = (-1)^{i-1} (i-1)!fi​=(−1)i−1(i−1)!(没错这其实可以用斯特林反演推。)
可是为什么要ef(x)=xe^{f(x)}= xef(x)=x呢?
因为对于一个恰好有kkk个相等块的方案,这kkk个块在我们枚举集合划分的时候都会被枚举到其子划分,那么这个方案被计算到的贡献是kkk个块的【子划分的容斥系数和】之积,所以一个大小大于1的集合他的所有子划分的容斥系数和应该为000,这样这kkk个块有任意一个大小大于111的块,他的贡献都是000。

然后根据出题人所描述,∑ai≤30\sum a_i\leq 30∑ai​≤30是一个很强的限制条件,所以我们可以状压DPDPDP求出所有∑ai\sum a_i∑ai​的整数分拆方案(≤5604\leq 5604≤5604种)所应该包含的容斥系数之和。然后O(nm)O(nm)O(nm)对所有整数分拆跑背包计算其方案数。(这复杂度怎么看都很炸)
这是什么神仙状压DPDPDP呢?
其实就是对于每个集合划分,我们不关注一个集合是由哪些数字组成的,只关注他的∑ai\sum a_i∑ai​和他的容斥系数也就是需要他包含的点数,那么就用set<pair<int,int>>set<pair<int,int>>set<pair<int,int>>代表一个集合划分,每个集合有∑ai=pair.first\sum a_i = pair.first∑ai​=pair.first,点数=pair.second= pair.second=pair.second,然后大力状压DPDPDP。(就离谱)
然后把firstfirstfirst抽出来作为整数分拆方案然后把secondsecondsecond作为容斥系数算入。
注意不能写set<pair<int,int>>set<pair<int,int>>set<pair<int,int>>,会TLETLETLE。
所以我们可以写pair<int,int>arr[30]pair<int,int>arr[30]pair<int,int>arr[30],然后每次sortsortsort后求hashhashhash值,为什么要求hashhashhash值呢,因为我们要大力状压dpdpdp,所以我们需要map<pair<int,int>arr[30]>map<pair<int,int>arr[30] >map<pair<int,int>arr[30]>,可是这样mapmapmap判断大小的时候又太慢(或许可以unordered_mapunordered\_mapunordered_map),所以我们要用hashhashhash值来O(1)O(1)O(1)判断大小,注意如果hashhashhash值相等,那么你必须认为这两个集合划分相等,否则如果你下去继续比较,就会TLETLETLE。(你或许不用知道我换了4个基才没有撞hash)

#include<bits/stdc++.h>
#define maxn 31
#define mod 1000000007
#define LL long long
using namespace std;int n,m,a[maxn],fac[maxn]={1,1},inv[maxn]={1,1},invf[maxn]={1,1};
int C(int a,int b){ if(a<0||b<0||a-b<0) return 0;return fac[a] * 1ll * invf[b] % mod * invf[a-b] % mod; }
LL pw11[2 * maxn];struct Set{#define pii pair<int,int>pii a[31];LL s;Set(){ memset(a,0,sizeof a),s=0; }void gethash(){ sort(a,a+31,greater<pii >());s = 0;for(int i=0;i<31 && a[i].first;i++) s += a[i].first * pw11[i] + a[i].second * pw11[i + 30];}bool operator <(const Set &B)const{return s < B.s;}
};
map<Set,int>dp[2];
map<vector<int>,int>xs;void add(int &a,int b){ a = (a+b) % mod; }
int upd(int a){ return a>=mod?a-mod:a; }int pr[10004],vis[10004],cnt_pr,e[10004],f[10004];int main(){scanf("%d%d",&n,&m);pw11[0] = 1;for(int i=1;i<=60;i++) pw11[i] = pw11[i-1] * 131;for(int i=2;i<=30;i++) fac[i] = 1ll * fac[i-1] * i% mod,inv[i] = 1ll * (mod - mod / i) * inv[mod % i] % mod,invf[i]  =1ll * invf[i-1] * inv[i] % mod;for(int i=1;i<=m;i++)scanf("%d",&a[i]);sort(a+1,a+1+m);int now = 1 , pre = 0;dp[now][Set()] = 1; for(int i=1;i<=m;i++){swap(now,pre);dp[now].clear();for(map<Set,int>::iterator it = dp[pre].begin();it!=dp[pre].end();it++){static Set u; int w = (*it).second;for(int j=0;j<31 && (j == 0 || (*it).first.a[j-1].first);j++){u=(*it).first , u.a[j].first += a[i] , u.a[j].second ++;u.gethash();add(dp[now][u],w);}}}for(map<Set,int>::iterator it = dp[now].begin();it!=dp[now].end();it++){static Set u; u = (*it).first; int w = (*it).second;vector<int>r;for(int i=0;i<31 && u.a[i].first;i++){r.push_back(u.a[i].first);w = 1ll * w * fac[u.a[i].second-1] * (u.a[i].second&1 ? 1 : -1) % mod;}add(xs[r],w);}int ans = 0;for(int i=2;i<=n;i++){if(!vis[i]) pr[cnt_pr++] = i;for(int j=0;pr[j]*i <= n;j++){vis[i * pr[j]] = 1;if(i % pr[j] == 0) break;}}for(int i=0;i<cnt_pr;i++){int t = n;for(;t;) e[i] += t / pr[i] , t /= pr[i];}for(map<vector<int>,int>::iterator it = xs.begin();it!=xs.end();it++){const vector<int>&r = (*it).first; int coe = (*it).second;memset(f,0,sizeof f);f[0] = 1;for(int i=0;i<r.size();i++)for(int j=r[i];j<=e[0];j++)f[j] = upd(f[j-r[i]] + f[j]);int sm = 1;for(int i=0;i<cnt_pr;i++)sm = 1ll * sm * f[e[i]] % mod;;ans = (ans + 1ll * sm * coe) % mod;}for(int i=1,j;i<=m;i=j){for(j=i;j<=m&&a[i]==a[j];j++);ans = 1ll * ans * invf[j-i] % mod;}printf("%d\n",(ans+mod)%mod);
}

省选模拟 幻化成风(容斥原理,状压DP)相关推荐

  1. [HNOI2012]集合选数(思维构造 + 状压dp)

    problem 题目链接 solution 从最小一个数 xxx 开始,将其 2x,3x2x,3x2x,3x 放入,再将 2(2x),3(2x),2(3x),3(3x)2(2x),3(2x),2(3x ...

  2. BZOJ 2734 [HNOI2012]集合选数 (状压DP、时间复杂度分析)

    题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=2734 题解 嗯早就想写的题,昨天因为某些不可告人的原因(大雾)把这题写了,今天再来写题解 ...

  3. 【uoj#37/bzoj3812】[清华集训2014]主旋律 状压dp+容斥原理

    题目描述 求一张有向图的强连通生成子图的数目对 $10^9+7$ 取模的结果. 题解 状压dp+容斥原理 设 $f[i]$ 表示点集 $i$ 强连通生成子图的数目,容易想到使用总方案数 $2^{sum ...

  4. NOIP模拟 整数划分(数论,质因数分解,状压DP)

    这道题竟然暴力能拿到90分,大佬orzorzorz%%%%%%%%%%% --------------------------分割线(下面是正解)--------------------------- ...

  5. 【2022国赛模拟】无损加密——LGV引理、状压DP

    原创题无来源 题目描述 题解 首先把问题稍作简化,我们可以最后把行列式乘上所有 dkd_kdk​ 的积的 nnn 次方,这样前面的过程就不用考虑 dkd_kdk​ 了,暴力也只需要变动 [lk,rk] ...

  6. 【gmoj4743】【8.11模拟赛T1】积木【状压DP/暴搜】

    题目链接:积木 分析 这题数据也太水了吧我喜欢 可以直接暴力搜索每一个积木的每一个顺序的每一种放置方法. 阶乘级别的复杂度,居然能过就离谱. 正解是状压DP.f[i][j][k]f[i][j][k]f ...

  7. 2021.8.11【提高B组模拟3】T1 积木(乱糊暴搜)(正解:状压dp)

    积木 题目大意 输入样例 3 8 7 6 3 9 4 1 10 5 输出样例 18 题目数据 解题思路 暴搜就没什么好讲的了 原本以为只有40,AC了就离谱 (数据真水) 正文:状压dp 前提:我这个 ...

  8. 牛客推荐系统开发之选飞行棋子(状压dp)

    链接:登录-专业IT笔试面试备考平台_牛客网 牛客的新开发的推荐系统使得牛客的DAU(日活跃用户数量)上升了一个档次,于是牛客的老板组织了一场团建.在团建时,牛牛.牛妹.王清楚和茶山牛四人想要愉快地玩 ...

  9. 【每日DP】day2、P1879 [USACO06NOV]Corn Fields G玉米地(状压DP模板题)难度⭐⭐⭐★

    昨天的每日DP我还在写01背包,今天就到状压DP了,真刺激. P1879 [USACO06NOV]Corn Fields G 题目链接 输入 2 3 1 1 1 0 1 0 输出 9 一道简单的状压D ...

最新文章

  1. 用法 stl_PoEdu培训第四课-C++之STL
  2. 如何在ASP.NET服务器控件库中嵌入JavaScript脚本文件 [适用于.NET 2.0]
  3. Python之IO编程——文件读写、StringIO/BytesIO、操作文件和目录、序列化
  4. mapreduce 算法_MapReduce算法–了解数据联接第1部分
  5. 零基础自学java_零基础学Java——小白的Java之路(4)
  6. php重定义地址栏url,thinkphp框架实现路由重定义简化url访问地址的方法分析
  7. mysql_connect() 不支持 请检查 mysql 模块是否正确加载 解决方法
  8. ACM学习历程—HDU1584 蜘蛛牌(动态规划 状态压缩 || 区间DP)
  9. 盘点 常见MQ : 消息队列总览
  10. Windows中Python3.x下运行Python2.x程序解决方案
  11. 两个苹果手机怎么定位_苹果手机录屏怎么开
  12. 机械硬盘更换成固态硬盘,重做 win10系统
  13. 【实时渲染】实时渲染中的光与颜色
  14. OS及Mac开源项目和学习资料【超级全面】
  15. 空白新机设置——让新电脑nice一些
  16. go 文件读Read and ReadString
  17. 利用pandoc把latex文件转换为word的基本操作
  18. 数据库系统是什么?它由哪几部分组成?
  19. 数字电子技术复习第二章
  20. 什么是序列化、反序列化

热门文章

  1. MYSQL安装时缺少MSVCP120.dll和MSVCR140.dll的修复工具,本人已修复并成功安装使用MYSQL
  2. Python实现PageRank计算
  3. poj 2524 Ubiquitous Religions (简单并查集)
  4. 2017渐入正轨,2018放眼未来
  5. 关于css的position属性的描述
  6. Java知识体系最详细总结(2020版)
  7. windows11除Edge、Chrome浏览器可联网,其他软件均无法联网问题
  8. 关于微信认证--个体工商户中之认证联系人
  9. SQL查询优化器浅析-字节跳动大数据青训营
  10. IT项目管理 第五章 习题