D https://codeforces.com/contest/2176/problem/D
哎哎,经典的赛后过题。分享D的另一种不同的思路。
Hint1 首先可以观察到除了单独一条边成斐波那契数列的情况,其它更长的数列情况中,除了作为开头的两个点,其它的点都是严格单调递增的。
根据这个这个观察我们可以把图上原来{u,v}(ta[u]<ta[v])的边删除。这样就变成有向无环图了。
再运用dfs回溯+dp(可以参考代码理解),最后再加上单独一条边成斐波那契数列的情况就可以了。
附上代码
int n,m;cin>>n>>m;
int ans=m;
vvi g(n+1),g1(n+1);
vi din(n+1);
vi ta(n+1);
for (int i=1;i<=n;i++) cin>>ta[i];
for (int i=1;i<=m;i++)
{
int u,v;cin>>u>>v;
g[u].push_back(v);
}
for (int i=1;i<=n;i++)
{
vi tc;
for (auto v:g[i])
{
if(ta[v]>ta[i])
{
tc.push_back(v);
}
}
g1[i]=g[i];
g[i]=tc;
}
for (int i=1;i<=n;i++)
{
auto tv=g[i];
for (auto v:tv)
{
din[v]++;
}
}
vi dp(n+1);
vi vis(n+1);
vector<map<int,int>> cnt(n+1);
auto dfs=[&](auto self,int u)->void
{
vis[u]=1;
// cout<<u<<endl;
for (auto v:g[u])
{
din[v]--;
if(vis[v]==0)
self(self,v);
cnt[u][ta[v]-ta[u]]=(cnt[u][ta[v]-ta[u]]+cnt[v][ta[u]]+1)%mod;
}
};
for (int i=1;i<=n;i++)
{
if(!din[i]&&vis[i]==0)
{
// cout<<i<<endl;
dfs(dfs,i);
}
}
for (int i=1;i<=n;i++)
{
for (auto v:g1[i])
{
ans=(ans+cnt[v][ta[i]])%mod;
}
// cout<<i<<" "<<ans<<endl;
}
cout<<ans<<endl;