问题F:散步

小兔要和小鹿一起散步。

现在小兔已经选好了她的约会场所,并将它划分为 n 块区域。他们游览完i号区域会走向第vi号区域。

小兔想要在区域内种上一些小鹿喜欢的花,共有 m 种。为了使散步时不乏味,第 vi号区域的花的种类不能和第 i 号区域一样。

热爱计算的小兔想求有多少种种花方案满足上述条件,她一秒钟就求出来了,但她想D您,所以也叫您解决这个问题。

因为结果可能很大,所以只要输出方案数除以 10007 的余数。
输入
第一行包含两个正整数 n,m,中间由一个空格隔开,表示区域个数和小鹿喜欢的花的种类数。
接下来 n 个数 vi,表示游览完i号区域会走向第 vi号区域。
输出
仅一行,一个正整数,表示方案数除以 10007 的余数。
样例输入 Copy
2 3
2 1
样例输出 Copy
6
代码如下。

这个题,每个点都只有一个出去的点,即出度都为1,入度不确定
所以,每个连通块都存在一个环,在环上的点,爆搜找答案
不在环上的,对答案的贡献只有m-1
#pragma GCC optimize(3,"Ofast","inline")
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+5;
const double eqs=1e-7;
int to[maxn],vis[maxn],diss[maxn];
const ll mod=10007;
int bb,n;
ll m,ans=1;
ll dfs2(ll xt,ll bt,int i)
{
    diss[i]=1;
    if(diss[to[i]]) return bt;
    ll xxt=bt,bbt=xt*(m-1)%mod+bt*(m-2)%mod;
    return dfs2(xxt,bbt%mod,to[i]);
}
void dfs1(int i)
{
    if(vis[to[i]]==bb)
    {
        ans=ans*dfs2(1,0,i)%mod*m%mod;
        diss[i]=2;
        vis[i]=bb;
        return ;
    }
    vis[i]=bb;
    if(!vis[to[i]]) dfs1(to[i]);
}
int main()
{
    scanf("%d %lld",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&to[i]);
    }
    for(int i=1;i<=n;i++)
    {
        bb=i;
        if(!vis[i])
        {
            dfs1(i);
        }
        if(diss[i]==0) ans=ans*(m-1)%mod;
    }
    printf("%lld\n",ans);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值