NOIP2020正式赛 排水系统(water)题解

在这里插入图片描述
这道题是拓扑序的板子题。
直接拓扑序一下,做个分数加法就好
但是这道题的数据范围让人暴毙。
在这里插入图片描述
分母最大值可以达到 6 0 11 = 36279705600000000000 60^{11}=36279705600000000000 6011=36279705600000000000,(60是将1/5,1/4,1/3,1/2,1/1合并出来最大的分母)
我就是无数lcm先乘后除的oier之一,炸成60
这道题用unsigned long long都不行, 2 64 − 1 = 18446744073709551615 2^{64}-1=18446744073709551615 2641=18446744073709551615,不够大
解决方案:
1.用int128,但是NOIP系列竞赛不能用
2.打高精度,在考场会让人自闭
3.用long double!
但是需要解决mod问题:小数如何取模?
cmath中有fmod函数可以解决这个问题。
于是这道题就比较简单了。













#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
#define ll long long
#define ldb long double
#define N 200005
#define eps 1e-6
using namespace std;
ll f[N*5][3],q[N],du[N],len[N],ans[N];
queue<ll> h;
ll i,j,k,m,n,o,p,l,s,t;
struct node{
   
   
	ldb x,y;
}a[N],ad,c;
void read(ll &x)
{
   
   
	char ch=getchar();x=0;
	while (ch<'0'||ch>'9') ch=getchar();
	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-48,ch=getchar();
}
void insert(ll x,ll y) {
   
   f[++t][1]=y,f[t][2]=q[x],q[x]=t;}
ldb mod(ldb x,ldb y) {
   
   return fmod(x,y);}
ldb gcd(ldb x,ldb y) {
   
   return (mod(x,y)>eps)?gcd(y,mod(x,y)):y;}
node change(ldb x,ldb y) {
   
   ll gys=gcd(x,y);return (node){
   
   x/gys,y/gys};} 
node operator +(const node &a,const node &b) {
   
   ll gys=gcd(a.y,b.y);c.y=a.y/gys*b.y;c.x=c.y/a.y*a.x+c.y/b.y*b.x;return c;}
int main()
{
   
   
	read(n),read(m);
	for (i=1;i<=n;i++)
	{
   
   
		read(len[i]);
		for (j=1;j<=len[i];j++) read(p),insert(i,p),du[p]++;
		if (!len[i]) ans[++ans[0]]=i;
	}
	for (i=1;i<=n;i++)
		if (!du[i]) h.push(i),a[i]=(node){
   
   1,1};
		else a[i]=(node){
   
   0,1};
	while (!h.empty())
	{
   
   
		ll st=h.front();h.pop();
		if (!len[st]) continue;
		ad=change(a[st].x,a[st].y*len[st]);
		for (ll k=q[st];k;k=f[k][2])
		{
   
   
			a[f[k][1]]=a[f[k][1]]+ad;
			du[f[k][1]]--;
			if (!du[f[k][1]]) h.push(f[k][1]);
		}
	}
	for (i=1;i<=ans[0];i++) a[ans[i]]=change(a[ans[i]].x,a[ans[i]].y),printf("%.0LF %.0LF\n",a[ans[i]].x,a[ans[i]].y);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章