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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章