UVA 11174 - 조합 수학 + 조합 수 취 모 + dfs
제목:
n 개인 과 일부 부자 관 계 를 제시 하고 이 n 개인 에 대해 하나의 배열 을 요구 하 며 그 중에서 아버 지 는 반드시 아들 의 앞 에 서 야 한다.모두 몇 가지 배열 방식 이 있 느 냐 고 물 었 다.
일부 아버지 가 없 는 사람 은 그 가 조상 이라는 것 을 나타 낸다.
모든 조상 노드 에 대해 우 리 는 그 를 뿌리 로 하 는 나무 내부 에서 요구 하 는 합 법 적 인 정렬 방안 을 S [1] 로 한다. 그래서 우 리 는 S [2], S [3] 를 얻 었 다.
모든 나무 에 총 노드 수 는 num [1], num [2]... num [k] 로 기록 합 니 다.
모든 나무 에 대해 그들 사이 의 노드 는 영향 을 주지 않 고 서로 삽입 할 수 있다.
마지막 으로 구 하 는 것 은 길이 가 n 인 서열 이다.
ans=1;
첫 번 째 나무 에 대해 서 는 ans=ans* C(N,num[1])*S【1】;//n 개의 위치 에서 num [1] 개의 위 치 를 선택 하고 이 나 무 를 놓 는 s [1] 가지 방안 을 나타 낸다.
마찬가지 로 두 번 째 나무 에 대해 서 는 ans=ans* C(N-num[1],num[2])*S【2】;//남 은 N - num [1] 개의 위 치 를 num [2] 개의 위치 로 선택 하고 이 나 무 를 놓 는 s [2] 가지 방안 을 나타 낸다.
.......
그럼 요구 하 는 건 num [], S [], 그리고 하나의 조합 수
num 에 대해 dfs 로 루트 노드 를 한 번 검색 하면 됩 니 다. (점 마다 검색 할 필요 가 없습니다. TLE 를 할 수 있 습 니 다. 루트 노드 만 검색 하면 됩 니 다)
S [] 에 대해 서도 dfs 입 니 다. 하위 트 리 의 내부 정렬 방안 수 를 계산 하 는 방법 은 마지막 으로 모든 하위 트 리 간 의 답 [빨간색 글꼴 부분] 을 계산 하 는 것 과 같 습 니 다.
조합 수 에 대해 모델 은 하나의 소수 이기 때문에 직접 역 원 으로 조합 계산 중의 계승 상 제 부분 을 계산 하면 된다.
ac 코드:
<pre name="code" class="cpp">#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <map>
#include <set>
#include <vector>
using namespace std;
const long long mod =1000000007;
long long fast_m(long long a,long long b)
{
long long x,ans=1;
x=a;
while(b)
{
if (b&1)
ans=(ans*x)%mod;
x=(x*x)%mod;
b/=2;
}
return ans;
}
long long fac[40005]; //
long long cal(long long x,long long y) //
{
long long ans=1;
ans*=(fac[x]*fast_m(fac[y]*fac[x-y]%mod,mod-2))%mod;
//(a/b)%mod, (a*b^(mod-2))%mod mod
return ans%mod;
}
vector<long long> tm[40005]; // i
long long total[40005]; // i
int vis[40005]; //vis[i]=1 【 】
long long an[40005]; // i ,
long long dfs(long long x); // an
long long cal_son(long long x); // total
int main()
{
long long i;
fac[0]=1;
for( i=1;i<=40000;i++)
fac[i]=fac[i-1]*i%mod;
int t;
cin>>t;
while(t--)
{
memset(an,0,sizeof(an));
memset(vis,0,sizeof(vis));
long long n,m;
scanf("%lld%lld",&n,&m);
for (i=1;i<=n;i++)
tm[i].clear();
long long tmp,fa;
for (i=1;i<=m;i++)
{
scanf("%lld%lld",&tmp,&fa);
tm[fa].push_back(tmp);
vis[tmp]=1;// tmp
}
for (i=1;i<=n;i++)
{
if (vis[i]) continue;
if (tm[i].size())
{
cal_son(i) ; // 【 】
}
else
total[i]=1; //
}
for (i=1;i<=n;i++)
{
if (vis[i]) continue; //
if (tm[i].size())
dfs(i); //
}
long long ans=1;
long long tmp_n=n;
for (i=1;i<=n;i++)
{
if (vis[i]) continue;//
ans=ans*cal(tmp_n,total[i])%mod;
tmp_n-=total[i]; // .. n , RE
if (an[i]) // ,
ans=ans*an[i]%mod;
}
printf("%lld
",ans%mod);
}
return 0;
}
long long dfs(long long x)
{
long long ans=1,i;
for (i=0;i<tm[x].size();i++)
{
long long tt=tm[x][i];
if (tm[tt].size())
{
dfs(tt); //RE , dfs(i)
}
}
long long sum=total[x]-1;
for (i=0;i<tm[x].size();i++)
{
long long num=tm[x][i];
long long tt=total[num];
ans=ans*cal(sum,tt)%mod;
if (an[num])
ans=ans*an[num]%mod;
sum-=tt;
}
return an[x]=ans%mod;
}
long long cal_son(long long x)
{
int son=0;
son+=tm[x].size();
int i;
for (i=0;i<tm[x].size();i++)
{
long long tt=tm[x][i];
if (tm[tt].size())
{
son+=cal_son(tt); //RE , dfs(i)
}
else
{
total[tt]=1;
}
}
total[x]=son+1; //
return son;
return 0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.