比赛过程中以为模拟就能过www,结果花了很长时间也没有调出来。稍微解释一下自己的代码:
vector<long long> adj[]是一个记录中子来源的动态数组;neu_0[]是记录从外面打进来的中子(也就是题干里指出的vi)的数组last_neutron[] 是记录上一秒打进来的中子数的数组(因为这一秒的裂变仅仅依赖于上一秒和vi)同时,我注意到经过有限长的时间后体系一定会达到稳态,也就是我代码中写到的:
stable_boundary=i=1∑na[i]在经过stable_boundary的时间后,所有可裂变的原子都开始裂变。因此在stable_boundary + 1至k的时间内各个原子接收到的中子数亦不变,不必进行模拟,可直接用乘法计算。
理论上我的程序的复杂度应该在O(m+n+min(k,∑a[i])×(n+∑a[i]))。实际测试的时候Subtest 0全对,Subtest 1第一个点TLE,,第二个点AC,其余测试WA。
求助大佬 QAQ~
#include<bits/stdc++.h>
using namespace std;
long long neutron[500001],a[500001],ans[500001],neu_0[500001];
int mod=998244353;
vector<long long> adj[500001];
long long n,k,m;
int main(){
scanf("%lld %lld %lld",&n,&k,&m);
if(m==0 or k==0){for(int i=1;i<=n;i++)printf("%lld ",0ll);return 0;}
for(int i=0;i<m;i++){
int tmp;
scanf("%d",&tmp);
neutron[tmp]++;
}
long long stable_boundary=0;
memcpy(neu_0, neutron, sizeof(neutron));
for(int i=1;i<=n;i++){
int tmp;
scanf("%lld",&a[i]);
stable_boundary+=a[i];
for(int j=0;j<a[i];j++){
scanf("%d",&tmp);
adj[tmp].push_back(i);
}
}
for(long long i=1;i<=min(stable_boundary+1,k);i++){
long long last_neutron[500001];
memcpy(last_neutron, neutron, sizeof(neutron));
bool stable=true;
for(int j=1;j<=n;j++){
neutron[j]=neu_0[j];
for(auto h:adj[j]){
if(last_neutron[h])neutron[j]++;
}
if(last_neutron[j])ans[j]=(ans[j]+(a[j]+last_neutron[j]))%mod;
if(neutron[j]!=last_neutron[j])stable=false;
}
if(stable){
long long remaining_time=k-i;
for(int j=1;j<=n;j++)ans[j]=(ans[j]+(remaining_time*(a[j]+last_neutron[j]))%mod)%mod;
break;
}
}
for(int i=1;i<=n;i++)printf("%lld ",ans[i]);
printf("\n");
return 0;
}