CF 852E Casinos and travel

題目連接spa

\(Desccription\)
給定一棵樹,John從任意一個點開始,每次走向一個未到達過的點。每一個點均可以有或沒有賭場,每通過一個賭場心情都會反轉,旅行開始前心情很好。
問有多少種方案使得旅行結束後心情很好。code

\(n≤10^5\)ip


\(Solution\)
把題目抽象一下:
每一個點隨機一個\(0/1\)的權值,隨機選擇一個點做爲根,有多少種方案使得根節點到全部葉節點路徑上的異或和爲\(0\)get

發現葉節點到根的路徑的權值異或和能夠由葉節點肯定。記葉節點數爲\(tot\)
1.若所選的根節點不是葉節點,那麼除葉節點外的\(n-tot\)個點的權值能夠隨便選,方案數爲\((n-tot)\times 2^{n-tot}\)
2.若所選的根節點是葉節點,那麼除其餘\(n-tot-1\)個葉節點外的全部的點權值能夠隨便選,方案數爲\(tot\times 2^{n-tot+1}\)io

\(ans=(n-tot)\times 2^{n-tot}+tot\times 2^{n-tot+1}=(n+tot)\times 2^{n-tot}\)class

#include<complex>
#include<cstdio>
using namespace std;
const int mod=1e9+7;
const int N=1e5+7;
int n,tot;
int in[N];
int qread()
{
    int x=0;
    char ch=getchar();
    while(ch<'0' || ch>'9')ch=getchar();
    while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x;
}
long long Fpow(long long b,int p)
{
    long long res=1;
    for(;p;p>>=1,b=b*b%mod)
        if(p&1)res=res*b%mod;
    return res;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<n;i++)
        in[qread()]++,in[qread()]++;
    for(int i=1;i<=n;i++)
        if(in[i]==1)tot++;
    printf("%d\n",(n+tot)*Fpow(2,n-tot)%mod);
    return 0;
}
相關文章
相關標籤/搜索