首页 > 其他分享 >【题解】CF - 823C : Coin Troubles

【题解】CF - 823C : Coin Troubles

时间:2024-08-15 13:16:09浏览次数:7  
标签:限制 硬币 int 题解 sum find 823C Coin 节点

原题传送门

题目大意

有 \(N\) 种硬币,两种硬币的面值可能相同。给定 \(q\) 个限制,第 \(i\) 个限制由 \(b_i\) 和 \(c_i\) 组成,表示第 \(b_i\) 种硬币的数量严格大于第 \(c_i\) 种硬币的数量,且每个 \(b_i\) 与 \(c_i\) 都是唯一的。问在满足所有限制的情况下,有多少种可能的方案,能组成正好等于 \(t\) 的总面值,并将方案数对 \(10^9 + 7\) 取模。

题意分析

不难看出,这题里的限制具有方向性,我们将每条限制看作一条从 \(c_i\) 指向 $ b_i$ 的有向边,此时如果出现了环,则限制一定不成立,故方案数为 \(0\) ; 否则,我们就可以将所有限制画成一个有向无环图。由于每个 \(b_i\) 与 \(c_i\) 都是唯一的,故每个节点的入度和出度都为 \(1\) ,即这个有向无环图一定是一条链,从这条链的头部开始,每个节点的后继币种的数量一定严格大于当前节点。
此时我们发现,如果一条链的某个节点被选了 \(i\) 次,它的后继节点则至少被选择 \(i + 1\) 次才能满足限制条件,因为一种硬币最少选 \(0\) 次,所以在符合限制的情况下,一条链的头部节点最少选 \(0\) 次,一号节点最少选 \(1\) 次,二号节点最少选 \(2\) 次,以此类推。故这些硬币无论方案最终如何,是必须要至少选这些次数的,我们就可以将它们从 \(t\) 中剔除。而在当前情况下,因为所有硬币都已经最少,且必须保持严格上升,所以更新链上的其中一个节点时,它的所有后继节点都必须要相应更新。但是题目没有要求我们求出方案本身,只要求输出方案数,我们便可以视为我们在更新时,更新了一枚币值等于当前节点以及它的所有后继的总币值的硬币。此时便解决了后效性问题,可以用完全背包求解。

AC代码

#include <bits/stdc++.h>

#define N 100050
#define int long long    //不开 long long 见祖宗
#define mod (1000000007LL)

using namespace std;

int t, n, q;
int a[350], pre[N], f[N], son[N], head[350], vis[350], b[350];
int sum, tmp;

int find(int x){    //找链的头部
	if(pre[x] == 0) return head[x] = x;
	return head[x] = find(pre[x]);
}

signed main(){
	cin >> n >> q >> t;
	for(int i = 1; i <= n; i++)	cin >> a[i];
	for(int i = 1; i <= n; i++) head[i] = i;
	for(int i = 1; i <= q; i++){
		int x, y;
		cin >> x >> y;
		if(find(x) == find(y)){cout << 0; return 0;}    //并查集判断环
		pre[x] = y; son[y] = x;
	}

	for(int i = 1; i <= n; i++) find(i);

	for(int i = 1; i <= n; i++) if(son[i] == 0) {
		for(int j = i; j != 0; j = pre[j]) tmp++;
		for(int j = i; j != 0 && tmp >= 0; j = pre[j]) 
			sum += --tmp * a[j],
			b[j] = a[j] + b[son[j]];
		t -= sum, tmp = 0, sum = 0;
		if(t < 0){cout << 0; return 0;}    //在满足限制的最少情况下就已经超过t,一定没有可行解
	}

	f[0] = 1;
	for(int i = 1; i <= n; i++)
		for(int v = 0; v + b[i] <= t; v++)
			f[v + b[i]] = (f[v + b[i]] % mod + f[v] % mod) % mod;    //好事多模

	cout << f[t] % mod;

	return 0;
}

标签:限制,硬币,int,题解,sum,find,823C,Coin,节点
From: https://www.cnblogs.com/XHyair-blogs/p/18360446

相关文章

  • Django 数据库迁移:makemigrations 和 migrate 命令详解及常见问题解决
    目录1.问题所示2.pythonmanage.pymakemigrations3.pythonmanage.pymigrate4.拓展1.问题所示最初始的状态是遇到这个问题由于刚开始跑pythonweb项目,开源项目附带的Readme,个别命令不太懂,对此详细研究其基本知识最终的解决方案如下:清理迁移文件:删除迁移目......
  • 大模型面试题库精华:100道经典问题解析
    ↓推荐关注↓算法暑期实习机会快结束了,校招大考即将来袭。当前就业环境已不再是那个双向奔赴时代了。求职者在变多,岗位在变少,要求还更高了。最近,我们陆续整理了很多大厂的面试题,帮助网友解惑答疑和职业规划,分享了面试中的那些弯弯绕绕。喜欢本文记得收藏、关注、点赞,更......
  • Ubunto 24.04 下 Docker Desktop 打开无反应问题解决和原因
    背景系统环境:Ubuntu24.04LTSDocker版本:Dockerversion26.1.4问题表象:打开DockerDesktop之后,无任何反应,使用命令行直接运行DockerDesktop,提示:runningundersystemd解决方案命令行执行如下指令$sudosysctl-wkernel.apparmor_restrict_unprivileged_userns=0$......
  • 【题解】 对决
    题目描述【题目描述】已知n个人(编号为1..n)进行了m轮对决,且给出这m轮对决的结果。请根据这m轮对决的结果,计算出可以确定多少人的最终排名。【输入格式】第一行两个整数n,m表示总共有n个人,m场对决.以下m行,每行两个整数ai,bi,表示ai号的人战胜了bi号的人.......
  • CF1530D Secret Santa 题解
    ProblemSolution每个人初始不会给自己送礼物。如果每人要送礼的人都不一样,答案即为\(n\)。如果有两个或以上的人要送给同一个人礼物,假设有\(x\)个人要给同一个人送礼物,那么必有\(x-1\)个人要更改送礼的人,并将礼物送个\(x-1\)个没有礼物收的人。然而这样送礼物可能会导......
  • Coin Troubles题解(dp,拓扑序)
    CoinTroubles题解(dp,拓扑序)题目链接:https://codeforces.com/problemset/problem/283/C题意:有\(n\)种硬币,每种硬币都有一个价格\(ai\),现在有\(q\)个限制,每个限制会告诉你\((b,c)\),并要求\(b\)种硬币的数量严格大于\(c\)种硬币的数量。现在问你一共有多少种买硬币的方法,使得最后......
  • 【题解】CF - 859C : Pie Rules
    原题传送门题目大意:给定一个长为\(N(1\leqN\leq50)\)的序列,Bob和Alice轮流从序列的最前端进行以下操作之一:取出序列最前端的数,并将其加到自己的分数中;取出序列最前端的数,将其加到对方的分数中,则下一轮可继续操作。两人轮流操作直到序列被取完,分数多的一方获胜。若......
  • 暑期模拟赛题解
    暑期模拟赛题解CSP-J模拟赛2024.7.5CSP-J模拟赛1T1简单二分,判断即可。T2\(60pts\)的状压是好写的。至于\(100pts\),考虑dp状态的合并,由于\(m\)的级别很小,考虑对后\(m\)个数状压,考察满足条件的情况。dp难以优化的时候考察本质相同的状态。T3数据范围显......
  • 【题解】【模拟】——帮贡排序
    【题解】【模拟】——帮贡排序帮贡排序题目背景题目描述输入格式输出格式输入输出样例输入#1输出#1提示1.题意解析1.1.结构体储存信息1.2.输入后调整职务的排序规则1.3.分配职务的方法1.4.职务的映射1.5.输出时的排序规则1.6.主函数2.代码帮贡排序题目背景在......
  • 洛谷P2789 直线交点数 题解
    解题思路考虑将直线分组,每组内直线互相平行,任意两组直线间交点数量等于两组内直线数量乘积。分组操作使用dfs,求出交点数量后加入set去重,输出set大小。时间复杂度O(2NN2)有点鬼畜但是可以通过。实现#include<cstdio>#include<unordered_set>inta[30];std::unordered_set......