uva 1436 - Counting heaps(計數)

來源:互聯網
上載者:User

標籤:style   blog   http   color   get   width   

題目連結:uva 1436 - Counting heaps

題目大意:給出一個樹的形狀,現在為這棵樹標號,保證根節點的標號值比子節點的標號值大,問有多少種標號樹。

解題思路:和村名排隊的思路是一隻的uva11174,最後問題只和樹德結構有直接關係,f(root)=(s(root)?1)!(s(1)?s(2)???s(n)

但是給定的模數數不是質數,所以不能用逆元做,只能將分子分母分別拆分成質因子,然後對質因子進位約分。因為最後的答案一定是正整數,所以對於每個質因子,分子分解出的因子個數一定大於等於分母分解出的,最後約分肯定剩下的是分子,再用快速冪求解。

剪枝,因為分解質因子的次數非常多,所以需要對分解函數剪枝,當u是質數時,可以直接終止返回。


#include <cstdio>#include <cstring>#include <queue>using namespace std;const int N = 500005;typedef long long ll;int P = 0, prime[N], ispri[N];int n, f[N], vis[N], cnt[N];ll mod;void getPrime (int N) {    memset(ispri, 0, sizeof(ispri));    for (int i = 2; i < N; i++) {        if (ispri[i])            continue;        prime[P++] = i;        for (int j = 2 * i; j < N; j += i)            ispri[j] = 1;    }}void getNode () {    memset(cnt, 0, sizeof(cnt));    queue<int> que;    for (int i = 1; i <= n; i++)        if (vis[i] == 0)            que.push(i);    while (!que.empty()) {        int u = que.front();        que.pop();        cnt[u]++;        int v = f[u];        cnt[v] += cnt[u];        vis[v]--;        if (vis[v] == 0)            que.push(v);    }}void init () {    memset(vis, 0, sizeof(vis));    scanf("%d%lld", &n, &mod);    f[1] = 0;    for (int i = 2; i <= n; i++) {        scanf("%d", &f[i]);        vis[f[i]]++;    }    getNode();    memset(vis, 0, sizeof(vis));    for (int i = 1; i <= n; i++)        vis[cnt[i]]++;}ll power (ll x, ll m) {    ll ans = 1;    while (m) {        if (m&1)            ans = ans * x % mod;        x = x * x % mod;        m /= 2;    }    return ans;}void cal (int u, int v) {    for (int i = 0; i < P; i++) {        int k = prime[i];        while (u % k == 0) {            cnt[k] += v;            u /= k;        }        if (ispri[u] == 0) {            cnt[u] += v;            return;        }    }}ll solve () {    memset(cnt, 0, sizeof(cnt));    for (int i = 2; i <= n; i++)        cal(i, 1);    for (int i = 2; i <= n; i++)        if (vis[i])            cal(i, -vis[i]);    ll ans = 1;    for (int i = 0; i < P; i++) {        ll u = prime[i];        if (cnt[u])            ans = (ans * power(u, cnt[u])) % mod;    }    return ans;}int main () {    getPrime(N);    int cas;    scanf("%d", &cas);    while (cas--) {        init();        printf("%lld\n", solve());    }    return 0;}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.