• 大(NOIP模拟赛Round #10)


    题目描述:

    小Z有个n个点的高清大图,每个点有且只有一条单向边的出边。现在你可以翻转其中的一些边,使他从任何一个点都不能通过一些道路走回这个点。为了方便,你只需输出方案数对取模即可。当在两个方案中有任意同一条边的方向不同,这两个方案视为不同。

    ————————————————我是分割线————————————————

    这道题目显然是结论题

    我们知道这道题只要把每一个环破坏掉就行了,然后我们考虑破坏一个环的方案数,假设一个环有n条边,那么方案数为:

    C(1,n)+C(2,n)+...+C(n-1,n)因为如果不翻转或者全部翻转那么都是环,不能满足题意

    然后我们考虑不是环的边,显然他们翻不翻转都不影响答案。假设有m条边不属于环,那么方案数为

    C(0,n)+...+C(n,n)

    由于我们知道公式

    C(0,n)+...+C(n,n)=2^n

    所以我们就能轻松得出结果啦

    #include<cstdio>
    #define MN 200005
    #define mod 1000000007
    using namespace std;
    int n,x,root=-1,dfsn,num,tt,total;
    int fis[MN],head[MN],rudu[MN];
    int huan[MN];
    bool visit[MN];
    long long ans=1;
    struct edge{
        int to,next;
    }g[MN];
    void ins(int u,int v){g[++num].next=head[u];head[u]=num;g[num].to=v;}
    long long mi(int now){
        long long tmp=2,res=1;
        while(now){
            if(now&1)res=(res*tmp)%mod;
            now>>=1;
            tmp=(tmp*tmp)%mod;
        }
        return res;
    }
    void dfs(int u){
        if(fis[u]){
            huan[++tt]=dfsn-fis[u]+1;
            return;
        }
        fis[u]=++dfsn;
        for(int i=head[u];i;i=g[i].next){
            if(!visit[g[i].to])dfs(g[i].to),visit[g[i].to]=true;
        }
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&x),ins(i,x);
        for(int i=1;i<=n;i++)if(!visit[i])dfs(i),visit[i]=true; 
        for(int i=1;i<=tt;i++)ans=(ans*(mi(huan[i])-2+mod)%mod)%mod,total+=huan[i];
        total=n-total;
        ans=(ans*mi(total))%mod;
        printf("%lld
    ",ans);
    }
  • 相关阅读:
    SQL Server 存储过程
    SQL数据类型介绍
    XML文件操作指南
    C# 程序集 与 反射
    详解C#中System.IO.File类和System.IO.FileInfo类的用法
    C# 之泛型详解
    C#中HashTable的用法示例2
    C#中HashTable的用法示例1
    DEDECMS5.7 首页和栏目页调用文章按权重排序
    linux创建用户,指定组
  • 原文地址:https://www.cnblogs.com/ghostfly233/p/7093859.html
Copyright © 2020-2023  润新知