题解 P7113 【排水系统】
这可能是我写的最后一篇题解了……T2看错题,用了 2h 获得了 0pts 的高分。
考场思路:
拓扑序板题???
再套个分数运算模板?
好像 ll 会炸,那就用 long double。
于是 30min 写完去看后面的题了。
代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
struct fs
{
unsigned int cnt2,cnt3,cnt5;
long double fz;
fs operator +(const fs x)
{
fs tmp=(fs){max(cnt2,x.cnt2),max(cnt3,x.cnt3),max(cnt5,x.cnt5),0};
long double tmp1=fz*pow(2,tmp.cnt2-cnt2)*pow(3,tmp.cnt3-cnt3)*pow(5,tmp.cnt5-cnt5);
long double tmp2=x.fz*pow(2,tmp.cnt2-x.cnt2)*pow(3,tmp.cnt3-x.cnt3)*pow(5,tmp.cnt5-x.cnt5);
tmp1+=tmp2;
while(round(tmp1/2)*2==tmp1&&tmp.cnt2>0)--tmp.cnt2,tmp1/=2;
while(round(tmp1/3)*3==tmp1&&tmp.cnt3>0)--tmp.cnt3,tmp1/=3;
while(round(tmp1/5)*5==tmp1&&tmp.cnt5>0)--tmp.cnt5,tmp1/=5;
tmp.fz=tmp1;
return tmp;
}
}ans[100001];
int n,m,d[100001],a[100001][11],in[100001],vis[100001];
void dfs(int i)
{
vis[i]=1;
if(--in[i]<=0)
{
if(d[i])
{
fs tmp=ans[i];
if(d[i]==2)tmp.cnt2+=1;
if(d[i]==3)tmp.cnt3+=1;
if(d[i]==4)tmp.cnt2+=2;
if(d[i]==5)tmp.cnt5+=1;
for(int j=1;j<=d[i];j++)ans[a[i][j]]=ans[a[i][j]]+tmp,dfs(a[i][j]);
}
}
}
signed main()
{
freopen("water.in","r",stdin);
freopen("water.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&d[i]);
for(int j=1;j<=d[i];j++)scanf("%d",&a[i][j]),++in[a[i][j]];
}
for(int i=1;i<=m;i++)ans[i].fz=1;
for(int i=1;i<=n;i++)if(in[i]==0&&vis[i]==0)dfs(i);
for(int i=1;i<=n;i++)
{
if(d[i]==0)
{
printf("%.0Lf %.0Lf\n",ans[i].fz,((long double)pow(2,ans[i].cnt2))*pow(3,ans[i].cnt3)*pow(5,ans[i].cnt5));
}
}
return 0;
}
赛后发现能卡掉,但是除了自己造的 hack 数据就没有别人卡掉(各种民间数据都是
这种写法基于浮点数的特性,long double 实际上会保存二进制最高 只要出题人没想到这种方法,就不会去卡。
再贡献两个 hack 数据(仅提供输入数据)。
爆搜复杂度是指数级的,本来只能拿 但是数据太水居然放过了,只要让每个点的出边都是
又到了亲手卡掉自己的代码的时候,long double 的 hack 数据只需要让分子的有效数位超过