Wannafly挑战赛26

题目连接

https://www.nowcoder.com/acm/contest/212#question

A. 御坂网络

枚举圆心所在的位置, O ( n ) O(n) O(n) 检查即可,总时间复杂度为 O ( n 2 ) O(n^2) O(n2)

B. 冥土追魂

这题比较坑,我感觉题意叙述有问题,总之也是一道水题,题解略去.

C. 七彩线段

题解

考虑到只有 7 7 7种颜色,因此可以枚举最后选出线段的颜色组合, 2 7 2^7 27种情况.

线段选法类似于会议安排,对于两个颜色相同的线段,我们必然优先选择右端点小的,因此我们第一步需要对线段以右端点从小到大进行排序.

预处理出数组 p r e [ i ] pre[i] pre[i],表示与线段 i i i不想交的右端点最大的线段是谁.

然后考虑状态压缩 d p dp dp:

d p [ i ] [ S ] dp[i][S] dp[i][S]表示考虑前 i i i个线段,已经选出来的线段颜色组合为 S S S,所取得的最大长度.

转移方程 d p [ i ] [ S ∣ ( 1 &lt; &lt; c o l o r [ i ] ) ] = m a x ( d p [ p r e [ i ] ] [ S ] , d p [ i − 1 ] [ S ( 1 &lt; &lt; c o l o r [ i ] ) ] ) dp[i][S | (1 &lt;&lt; color[i])] = max(dp[pre[i]][S],dp[i-1][S(1&lt;&lt;color[i])]) dp[i][S∣(1<<color[i])]=max(dp[pre[i]][S],dp[i−1][S(1<<color[i])])

代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#define pr(x) std::cout << #x << ':' << x << std::endl
#define rep(i,a,b) for(int i = a;i <= b;++i)
#define clr(x) memset(x,0,sizeof(x))
#define setinf(x) memset(x,0x3f,sizeof(x))
struct seg{int l,r,c;bool operator<(const seg& sg)const{return r < sg.r;}
};
std::vector<seg> segs;
int n,m;
long long dp[100007][1<<7];
int used[1 << 7];inline int cnt(int x) {int res = 0;while (x) {res++;x -= x & -x;}return res;
}
int pre[100007];
int main() {std::cin >> n >> m;for(int S = 0;S < (1<<7);++S) {if(cnt(S) == m) used[S] = 1;}for(int i = 0;i < n;++i) {int l,r,c;std::cin >> l >> r >> c;c--;segs.push_back((seg){l,r,c});}std::sort(segs.begin(),segs.end());for(int i = 0;i < n;++i) {int id = (std::lower_bound(segs.begin(),segs.end(),(seg){0,segs[i].l,0}) - segs.begin());--id;pre[i] = id;}long long ans = -1;dp[0][1<<segs[0].c] = segs[0].r - segs[0].l;for(int i = 1;i < n;++i) {dp[i][1 << segs[i].c] = segs[i].r - segs[i].l;for(int S = 0;S < (1<<7);++S) {dp[i][S] = std::max(dp[i][S],dp[i-1][S]);}if(pre[i] >= 0)for(int S = 0;S < (1 << 7);++S) {int nS = S|(1<<segs[i].c);if(dp[pre[i]][S])dp[i][nS] = std::max(dp[i][nS],dp[pre[i]][S] + segs[i].r - segs[i].l);}for(int S = 0;S < (1 << 7);++S) {if(used[S] && dp[i][S] > ans)ans = dp[i][S];  }}if(ans == 0) ans = -1;std::cout << ans << std::endl;
}

D.禁书目录

题解

我们考虑每种颜色被在排列中被计数了多少次.

[0]结论: 一本书不会消失当且仅当所有 a a a大于等于它的书都在它的右边.

因此假设有 t t t本书其 a i ≥ a x a_i \ge a_x ai​≥ax​,只考虑这 t t t本书的排列,书 x x x被看见的概率是 1 t \frac{1}{t} t1​.

[1]假设有书 a x &gt; a y a_x &gt; a_y ax​>ay​,且 a i ≥ a x a_i \ge a_x ai​≥ax​的有 t x t_x tx​本书, a i ≥ a y a_i \ge a_y ai​≥ay​的有 t y t_y ty​本书,显然 t x &lt; t y t_x \lt t_y tx​<ty​,我们希望求出 x x x和 y y y都没有出现的概率:

t x t_x tx​本书的相互排列中,书 x x x必然不能出现在第一个位置,这样概率是 t x − 1 t x \frac{t_x-1}{t_x} tx​tx​−1​.然后 t y t_y ty​本书中 y y y也不能出现在第一个位置, t x t_x tx​的排列对书 y y y的选择没有影响,因此概率是 t y − 1 t y \frac{t_y-1}{t_y} ty​ty​−1​,乘起来就是 t y − 1 t y ∗ t x − 1 t x \frac{t_y-1}{t_y}*\frac{t_x-1}{t_x} ty​ty​−1​∗tx​tx​−1​.

[2]假设有书 a x = a y a_x = a_y ax​=ay​,且 a i ≥ a x a_i \ge a_x ai​≥ax​的书有 t t t本,我们希望求出书 x x x和 y y y都没有出现的概率.先不考虑 a x a_x ax​,那么 a y a_y ay​不出现的概率是 t − 2 t − 1 \frac{t-2}{t-1} t−1t−2​,再考虑 a x a_x ax​不出现的概率是 t − 1 t \frac{t-1}{t} tt−1​,乘起来就是 t − 2 t \frac{t-2}{t} tt−2​,可以猜测有 k k k本书 a a a相同时,且 a i ≥ a a_i \ge a ai​≥a的书有 t t t本,那么这 k k k本书都没出现的概率是 t − k t \frac{t-k}{t} tt−k​

ps:我们为什么要求[2]呢,为什么 a x = a y a_x = a_y ax​=ay​时候,求两者都不出现的概率时候不能直接使用[0]结论呢?
这是因为
当对 a x a_x ax​使用结论[0]时候,默认 a y a_y ay​在 a x a_x ax​右侧,而再对 a y a_y ay​使用结论[0]时候,默认 a x a_x ax​在 a y a_y ay​右侧,这样就出现了矛盾,因此,当两者 a a a相等时,就不能直接用结论 0 0 0了,而需要扩展一下.

结合[1][2]两个结论,我们枚举每一种颜色,计数这些颜色的书每一本都没有被看到的概率.
然后最后用 1 1 1减去这个概率再乘以 n ! n! n!即是这部分颜色的贡献.

举个例子,当颜色为 c c c的书为
a 1 &lt; a 3 = a 5 &lt; a 6 &lt; a 7 a_1 &lt; a_3 = a_5 &lt; a_6 &lt; a _ 7 a1​<a3​=a5​<a6​<a7​ 时候是,对答案的贡献就是

n ! ∗ ( 1 − t 1 − 1 t 1 ∗ t 3 − 2 t 3 ∗ t 6 − 1 t 6 ∗ t 7 − 1 t 7 ) n! * (1-\frac{t_1-1}{t_1}*\frac{t_3-2}{t_3}*\frac{t_6-1} {t_6}*\frac{t_7-1}{t_7}) n!∗(1−t1​t1​−1​∗t3​t3​−2​∗t6​t6​−1​∗t7​t7​−1​)

其中 t i t_i ti​表示不小于 a i a_i ai​的书的本数.

代码

#include <iostream>
#include <algorithm>
#include <map>#define pr(x) std::cout << #x << ":" << x << std::endlconst int N = 1000007;typedef long long ll;
typedef std::pair<int,int> pii;
const ll P = 998244353;
std::map<int,ll> mp;
ll mod_pow(ll x,ll n) {ll res = 1;while(n) {if(n & 1) res = res * x % P;x = x * x % P;n >>= 1;}return res;
}
int n;
pii ps[N];
int main() {std::ios::sync_with_stdio(false);std::cin >> n;for(int i = 1;i <= n;++i) {int a,b;std::cin >> a >> b;ps[i-1] = (pii){a,b};}std::sort(ps,ps+n);ll ans = 0;ll nn = 1;for(int i = 1;i <= n;++i) nn = nn * i % P;int last = 0;for(int i = 0;i < n ;++i) {int pos = i;while(pos < n-1 && ps[pos] == ps[pos+1])++pos;if(mp.count(ps[pos].second) == 0) mp[ps[pos].second] = 1;if(ps[i].first != ps[last].first) last = i;ll big = n - last;mp[ps[pos].second] = mp[ps[pos].second] * (big - (pos - i + 1)) % P* mod_pow(big,P-2) % P;i = pos;}for(auto &p : mp) {ans = (ans + (nn * (1 + P - p.second) % P)) % P;}std::cout << ans << std::endl;
}

E.蚂蚁开会

待解决

F.msc的棋盘

题解

这其实是一道现寻找充要条件,然后使用 d p dp dp计数的题.

如果给出 a 数 组 a数组 a数组(行数组),和 b 数 组 b数组 b数组(列数组),要进行判定,那么我们想到了用网络流进行判定,如果满流的话,就表示判定成功.

如 n = 4 , m = 2 , b [ 1 ] = 1 , b [ 2 ] = 3 n = 4,m = 2,b[1] = 1,b[2] = 3 n=4,m=2,b[1]=1,b[2]=3时候,
左边一排点有 4 4 4个,右边一排点有 2 2 2个,且两排点之间两两有边容量为 1 1 1.源点向第一排点连边容量为 a [ i ] a[i] a[i],第二排点向汇点连边,容量为 b [ i ] b[i] b[i].

设 s u m = ∑ b [ i ] sum = \sum{b[i]} sum=∑b[i]

根据最大流最小割定理,也就是说图的最小割必然要 = s u m = sum =sum

考虑一个割选取了左边 x x x个点,右边 y y y个点,那么必然会选择左边 a [ i ] a[i] a[i]最小的前 x x x个点,同理右边会选择 b [ i ] b[i] b[i]最小的前 y y y个点.同样在剩下的没有选择的边中中间容量为 1 1 1的边都要被切掉.

用 s a , s b sa,sb sa,sb表示 a , b a,b a,b排好序的前缀和.

割 ( x , y ) = s a [ x ] + s b [ y ] + ( n − x ) ( m − y ) ≥ s u m 割(x,y) = sa[x] + sb[y] + (n-x)(m-y) \ge sum 割(x,y)=sa[x]+sb[y]+(n−x)(m−y)≥sum

且由于最大流 ≤ s u m \le sum ≤sum,所以保证了有 割 = s u m 割=sum 割=sum.

因此我们就得到了一个充要条件.

那就是所有的 割 割 割必然要 ≥ s u m \ge sum ≥sum,求方案数.

相当于要把 s u m sum sum个棋子,分给每一行,使得 割 割 割满足 ≥ s u m \ge sum ≥sum,的方案数.直觉告诉我们要用 d p dp dp来做.

定义 d p [ i ] [ j ] [ k ] dp[i][j][k] dp[i][j][k]表示考虑 a [ i ] a[i] a[i]前 i i i小的行,且最大行的 a [ i ] ≤ j a[i] \le j a[i]≤j,且 s a [ i ] = k sa[i] = k sa[i]=k的方案数.

转移方程:

d p [ i + t ] [ j + 1 ] [ k + t ( j + 1 ) ] + = d p [ i ] [ j ] [ k ] C n − i t , 且 0 ≤ t ≤ n − i dp[i+t][j+1][k+t(j+1)] += dp[i][j][k]C_{n-i}^{t},且0 \le t \le n-i dp[i+t][j+1][k+t(j+1)]+=dp[i][j][k]Cn−it​,且0≤t≤n−i

观察 d p dp dp方程,只有第二维严格递增,因此转移的时候我们先枚举第二维,然后再枚举第一维和第三维,这样保证了 d p dp dp的无后效性.

代码

#include <cstdio>
#include <iostream>
#include <algorithm>#define pr(x) std::cout << #x << ":" << x << std::endl
typedef long long ll;
const ll P = 1000000007;
const int N = 51;
int n,m;
ll dp[N][N][N*N];
// dp[i][j][k] 表示前i小的行都已经考虑完,第i小的行有j个棋子,且前i行总棋子数量为k的可能的方案数.int sa[N],sb[N];
//sa[i]表示前i小的行棋子总数的最小限度
ll C[N][N];
void init() {C[0][0] = 1;for(int i = 1;i < N;++i) {C[i][0] = 1;for(int j = 1;j <= i;++j) {C[i][j] = (C[i-1][j-1] + C[i-1][j]) % P;}}
}
ll fC(int n,int m) {if(m > n || m < 0) return 0;return C[n][m];
}
void add(ll &x,ll y) {x = x + y;if(x > P) x -= P;
}int main() {init();std::cin >> n >> m;for(int i = 1;i <= m;++i) std::cin >> sb[i];std::sort(sb+1,sb+1+m);for(int i = 1;i <= m;++i)sb[i] += sb[i-1];for(int i = 1;i <= n;++i) {int mi = 2500;for(int j = 1;j <= m;++j) {mi = std::min(mi,sb[j] + (n-i)*(m-j));}sa[i] = sb[m] - mi;}int lim = sb[m];for(int i = 0;i <= n && 0 >= sa[i];++i) {dp[i][0][0] = fC(n,i);}for(int j = 0;j <= m;++j) {for(int i = 0;i <= n;++i) {for(int k = 0;k <= lim;++k) {if(dp[i][j][k] == 0) continue;for(int t = 0;i+t <= n && k + t*(j+1) <= lim&& k + t*(j+1) >= sa[i+t];++t) {add(dp[i+t][j+1][k+t*(j+1)],dp[i][j][k]*fC(n-i,t)%P);}}}}std::cout << dp[n][m][lim] << std::endl;
}

Wannafly挑战赛26 题解相关推荐

  1. Wannafly挑战赛26题解

    为啥混进了几道不是魔禁的题--出题人太不敬业了-- 传送门 \(A\) 御坂网络 为啥没有番外个体和整体意志呢 暴力模拟就好了,这个要是都打错我干脆滚回去学文化课算了 //minamoto #incl ...

  2. Wannafly 挑战赛27 题解

    Wannafly 挑战赛27 题目连接 https://www.nowcoder.com/acm/contest/215#question A.灰魔法师 题目 题解 考虑到可能的完全平方数只有4004 ...

  3. Wannafly挑战赛29题解

    这套题目非常有意思啊23333--话说为啥没有上条先生的呢-- 传送门 \(A\) 御坂美琴 蠢了--首先先判总共加起来等不等于\(n\),不是的话就不行 然后dfs记录\(n\)不断分下去能分成哪些 ...

  4. Wannafly挑战赛26 御坂网络

    链接:https://ac.nowcoder.com/acm/contest/212/A 来源:牛客网 御坂网络 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 131072K,其他语 ...

  5. Wannafly挑战赛26 B.冥土追魂 贪心

    链接:https://www.nowcoder.com/acm/contest/212/B 来源:牛客网 题目描述 有一天 Misaka 和 Kuroko 在玩一个关于冥土追魂的游戏.... Misa ...

  6. Wannafly挑战赛26 B-冥土追魂(枚举)

    思路来源 优秀的组长哒哒哒 https://www.nowcoder.com/acm/contest/view-submission?submissionId=36142802 (红名白法师%%%)( ...

  7. Wannafly挑战赛26

    链接:https://www.nowcoder.com/acm/contest/212/A 作为「Misaka Network」的中心司令塔的 LastOrder出事了,为了维持 「Misaka Ne ...

  8. Wannafly挑战赛26: B. 冥土追魂(思维题)

    链接:https://www.nowcoder.com/acm/contest/212/B 来源:牛客网 题目描述 有一天 Misaka 和 Kuroko 在玩一个关于冥土追魂的游戏.... Misa ...

  9. Wannafly挑战赛26 B 冥土追魂

    首先,证明结果一定是取某些整行,再加上一个多余的一行的前几个. 假如: x1<=x2<=x3<=x4<=x5 y1<=y2<=y3<=y4<=y5 取6 ...

最新文章

  1. BundleTrack:无需实例或类级别3D模型的6D姿态跟踪算法(IROS2021)
  2. mybatis 动态字段与表中不一样_mybatis创建一个或多个新用户 insert 字段和表名不确定时动态添加问题...
  3. 钉钉小程序数据传递——子传父,父传子
  4. 一文入门 Kafka
  5. ExtJs Grid分页时序号自增的实现,以及查询以后的序号的处理
  6. SqoopFlume、Flume、HDFS之间比较
  7. MATLAB Primitive Types
  8. JAVA浮点数浮点数转换成人民币读法
  9. XP下使用submit text3遭遇死机强制重启导致以及代码数据丢失(无法读取源文件或磁盘)
  10. cv2.error: OpenCV(4.5.3) C:\Users\runneradmin\AppData\Local\Temp\pip-req-build-q3d_8t8e\opencv\modul
  11. HTML5正确嵌入flash,网页上嵌入Flash播放器(1)
  12. Redis客户端访问
  13. 无监督低照度图像增强网络ZeroDCE和SCI介绍
  14. 原厂对NPI安全稽核要求
  15. 晶体硅太阳能电池产线性能跟踪项目
  16. 用Modules优雅地管理你的环境变量
  17. API是用来干什么的
  18. 数字信号处理(3)- z变换
  19. 会飞的鲨鱼?记遥控氦气球的诞生
  20. beyond compare 3 中文乱码问题的解决

热门文章

  1. OSChina 周三乱弹 ——没见过这么漂亮的女司机啊!
  2. 滴滴总裁柳青,5000 亿估值和身家千亿同学背后的故事
  3. 怎么赚钱快?只要不是这三种人,都可以赚到钱!
  4. Eclipse导入外部jar依赖包简单易用过程
  5. 浦东新区企业研发机构认定奖励50万政策解读
  6. fixed计算机术语,fixed是什么意思
  7. 最终定档——华为(附校招流程)
  8. 为什么微信有时无法接收到服务器,微信小程序开启了消息推送,服务器有时候接收不到...
  9. nt5src去除激活的winlogon
  10. 【Python】近似熵,样本熵,模糊熵计算高效版