AtCoder AGC039F Min Product Sum (容斥原理、组合计数、DP)
题目链接
https://atcoder.jp/contests/agc039/tasks/agc039_f
题解
又是很简单的F题我不会。。。
考虑先给每行每列钦定一个最小值\(a_i,b_j\),并假设每行每列的最小值是这个数,且每行每列只需要放\(\ge\)这个数的数即可,那么这种情况的价值是\(\prod^n_{i=1}\prod^m_{j=1}\min(a_i,b_j)\), 方案数是\(\prod^n_{i=1}\prod^m_{j=1}(n+1-\max(a_i,b_j))\)
然后我们需要把最小值的限制容斥掉,也就是枚举若干行若干列容斥掉(限制\(+1\)同时系数乘以\(-1\))。
这样的话直接暴力DP就可以解决。设\(f[k][i][j]\)表示当前用\([1,k]\)中的数填满了\(i\)行\(j\)列。转移可以直接枚举不被容斥的行数、不被容斥的列数、容斥的行数、容斥的列数,乘上贡献系数,得到了一个多项式时间复杂度的算法。
但是我们发现这样转移显然很浪费,我们可以把四个变量同时枚举改成分四个阶段依次枚举,这样转移时间复杂度降到了\(O(n)\).(注意因为要保证从小到大填数,所以必须先枚举不被容斥再枚举被容斥)
不过这题还挺卡常的……需要\(O(n^3)\)预处理一下转移系数,详见代码
时间复杂度\(O(n^4)\)
orz myh
代码
#include<bits/stdc++.h>
#define llong long long
#define mkpr make_pair
#define riterator reverse_iterator
using namespace std;inline int read()
{int x = 0,f = 1; char ch = getchar();for(;!isdigit(ch);ch=getchar()) {if(ch=='-') f = -1;}for(; isdigit(ch);ch=getchar()) {x = x*10+ch-48;}return x*f;
}const int N = 100;
int P;
llong pw[N+3][N*N+3];
llong comb[N+3][N+3];
llong f[2][N+3][N+3];
llong trans[N+3][N+3];
int n,m,p;llong quickpow(llong x,llong y)
{llong cur = x,ret = 1ll;for(int i=0; y; i++){if(y&(1ll<<i)) {y-=(1ll<<i); ret = ret*cur%P;}cur = cur*cur%P;}return ret;
}void initmath()
{for(int i=0; i<=N; i++){pw[i][0] = 1ll; for(int j=1; j<=N*N; j++) pw[i][j] = pw[i][j-1]*i%P;}comb[0][0] = 1ll;for(int i=1; i<=N; i++){comb[i][0] = comb[i][i] = 1ll;for(int j=1; j<i; j++) comb[i][j] = (comb[i-1][j]+comb[i-1][j-1])%P;}
}llong updsum(llong &x,llong y) {x = x+y>=P?x+y-P:x+y;}int main()
{scanf("%d%d%d%lld",&n,&m,&p,&P);initmath();int curk = 0; f[0][0][0] = 1ll;for(int k=1; k<=p; k++){curk^=1; memset(f[curk],0,sizeof(f[curk]));for(int j=0; j<=m; j++) for(int ii=0; ii<=n; ii++) trans[j][ii] = pw[k][ii*(m-j)]%P*pw[p-k+1][ii*j]%P;for(int i=0; i<=n; i++){for(int j=0; j<=m; j++){llong x = f[curk^1][i][j]; if(!x) continue;for(int ii=0; ii+i<=n; ii++){updsum(f[curk][i+ii][j],x*comb[i+ii][i]%P*trans[j][ii]%P);}}}curk^=1; memset(f[curk],0,sizeof(f[curk]));for(int i=0; i<=n; i++) for(int jj=0; jj<=m; jj++) trans[i][jj] = pw[k][jj*(n-i)]%P*pw[p-k+1][jj*i]%P;for(int i=0; i<=n; i++){for(int j=0; j<=m; j++){llong x = f[curk^1][i][j]; if(!x) continue;for(int jj=0; jj+j<=m; jj++){updsum(f[curk][i][j+jj],x*comb[j+jj][j]%P*trans[i][jj]%P);}}}curk^=1; memset(f[curk],0,sizeof(f[curk]));for(int j=0; j<=m; j++) for(int ii=0; ii<=n; ii++) trans[j][ii] = pw[k][ii*(m-j)]%P*pw[p-k][ii*j]%P;for(int i=0; i<=n; i++){for(int j=0; j<=m; j++){llong x = f[curk^1][i][j]; if(!x) continue;for(int ii=0; ii+i<=n; ii++){llong y = x*comb[i+ii][i]%P*trans[j][ii]%P;updsum(f[curk][i+ii][j],ii&1?P-y:y);}}}curk^=1; memset(f[curk],0,sizeof(f[curk]));for(int i=0; i<=n; i++) for(int jj=0; jj<=m; jj++) trans[i][jj] = pw[k][jj*(n-i)]%P*pw[p-k][i*jj]%P;for(int i=0; i<=n; i++){for(int j=0; j<=m; j++){llong x = f[curk^1][i][j]; if(!x) continue;for(int jj=0; jj+j<=m; jj++){llong y = x*comb[j+jj][j]%P*trans[i][jj]%P;updsum(f[curk][i][j+jj],jj&1?P-y:y);}}}}printf("%lld\n",f[curk][n][m]);return 0;
}
AtCoder AGC039F Min Product Sum (容斥原理、组合计数、DP)相关推荐
- Educational Codeforces Round 81 (Rated for Div. 2) F.Good Contest \ 洛谷 划艇 组合 计数dp
cf传送门 P3643 [APIO2016]划艇 文章目录 题意: 思路: 题意: aia_iai在[li,ri][l_i,r_i][li,ri]等概率随机选一个数,求aaa数组不增的概率. 思 ...
- bzoj2111,P2606-[ZJOI2010]排列计数【Lucas,组合计数,dp】
正题 题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=2111 https://www.luogu.org/problem/P2606 题 ...
- 《算法竞赛进阶指南》数论篇(3)-组合计数,Lucas定理,Catalan数列,容斥原理,莫比乌斯反演,概率与数学期望,博弈论之SG函数
文章目录 组合计数 例题:Counting swaps Lucas定理 Cnm≡Cnmodpmmodp∗Cn/pm/p(modp)C_n^m\equiv C_{n\ mod\ p}^{m\ mod\ ...
- 解题报告(五)组合计数(ACM / OI)超高质量题解
繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量题解和代码,题目难度不一定按照题号排序,我会在每道题后面加上题目难度指数(1∼51 \sim 51∼5),以模板题难度 11 ...
- 基础组合计数常用的概念和方法总结
基础组合计数常用的概念和方法总结 一.组合计数中的基本概念与性质 1.排列 定义 性质 2.组合 定义 性质 二.组合计数中的一些常用技巧 1.容斥原理 定义 公式 2.捆绑与插空法 捆绑法 插空法 ...
- 数学知识——组合计数
组合计数 文章目录 组合计数 概述 动态规划 牡牛和牝牛 思路 代码 隔板法 方程的解 思路 代码 序列统计 思路 代码 加法 & 乘法原理 加法原理 乘法原理 车的摆放 思路 代码 容斥原理 ...
- 解题报告(二)E、(BZOJ3513) [MUTC2013] idiots(生成函数 + FFT + 组合计数)
繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量题解和代码,题目难度不一定按照题号排序,我会在每道题后面加上题目难度指数(1∼51 \sim 51∼5),以模板题难度 11 ...
- 数据结构之线段树Ⅴ——(李超线段树)Robot,Product Sum,Building Bridges,Jump mission
文章目录 Robot Product Sum Building Bridges Jump mission Robot BZOJ3938 机器人每次一旦改变速度,直到下一次改变速度为止 这一时间段内机器 ...
- 学组合数学心得与题解(一)——组合计数
今天我在某网站上稍微学习了一下组合数学,准确来讲,今天就看了看组合计数.像一些弱智的排列数.组合数大家肯定在小学奥数就已经精通了(只有我这种蒟蒻忘的精光).当然,博主比较菜,连二项式定理.帕斯卡恒等式 ...
最新文章
- Java线程池使用与原理
- 局域网连接其他机器命令_弱电工程师必备技能,PING命令使用方法大全
- 每日一题(开开森森学前端之变量与函数)
- 【数学基础】一份非常适合人工智能学习的高等数学基础材料中文版 (国内教材精华)...
- 牛客练习赛25 B-最长区间
- 您如何使用硒来计算自动化测试的投资回报率?
- 【★原创★】夜晚,不要让电白白流失!
- 用mysql制作一个登录_连接数据库制作一个简单的登入页面1
- php实现读写ic卡,diy用PIC单片机实现的IC卡读写器
- 怎样HTML做图片画廊,42个jQuery图片画廊插件
- Luyten反编译工具
- java html模板_Java实现静态页面模板替换内容代码
- 详解智慧城市排水管理系统整体方案
- 数字信号处理中均值、均方值、均方差、均方根值、均方误差、均方根误差、方差、协方差、标准差对比分析及统计学意义
- 手机H5如何对接支付宝登陆授权以及支付(H5网站支付)
- WebStorm使用-显示隐藏文件
- 九连环 C语言递归代码
- STM32WB55使用————Zigbee信息收发
- Enhanced Assertions
- java开发工程师面试自我介绍_Java程序员如何进行自我介绍