• SCUT


    https://scut.online/p/482

    没听说过这个东西。

    洛谷也有这个,所以还是要去接触一些奇奇怪怪的知识才行。
    https://www.luogu.org/problem/P2290

    画了一个表。

    1个点:

    F[1]=1

    2个点:

    F[1]=1
    F[2]=1

    3个点:

    F[1]=2/3
    F[2]=1/3
    F[3]=0

    4个点:

    F[1]=9/16
    F[2]=4/16
    F[3]=1/16
    F[4]=0

    没发现有什么规律,可能是真的要画到5才可以?


    Prufer序列,用于对同一形态的无根树映射到序列。用来解决只跟度数有关的树的问题。

    1.找度数为1的,且编号最小的点,把它的父亲加入Prufer序列,且把它删除。

    然后会得到一个n-2个点的序列,其中出现元素的次数就是他的度数-1。

    从Prufer恢复树:

    2.取出Prufer的第一个节点x,把不在Prufer里的最小元素y,在x-y之间连边。

    性质:

    1.prufer序列与无根树一一对应。

    2.度数为d_i的节点会在prufer序列中出现d_i-1次。

    3.一个n个节点的完全图的生成树个数为n^{n-2}。因为对于一个n个点的无根树,它的prufer序列长为n−2,而每个位置有n种可能性,因此可能的prufer序列有n^{n-2}种。很显然每一种无根树唯一对应完全图的一个生成树。

    4.对于给定度数序列为d_i的一棵无根树共有 (frac{(n-2)!}{prod_{i=1}^n(d_i-1)!}) 种情况。由上面的性质可以知道,度数为d_i的节点会在prufer序列中出现d_i-1次。则就是要求出d_i-1个i的全排列个数。而上面那个式子就是可重全排列公式。(即全排列个数除以重复元素内部的全排列个数)


    回到这一题,每种生成树对应一个Prufer序列,那么总共肯定是n^{n-2}种生成树,其中F[1]肯定是不选1,那么就是(n-1)^{n-2},以此类推。


    众所周知,幂函数是完全积性的。把它移动一下就可以了。


    还卡内存,真的毒瘤。开多一个F数组拿来复制都不行。
    事实上不需要这么强迫症,写个函数映射过去,或者直接在答案里面映射过去就可以了。

    试试证明bitset在单个访问的时候对时间的浪费程度比bool大。

    然而因为MOD是一个1e9+7,所以不会有任何比它小的数的幂次会MOD它为0,可以直接用G[i]来判断。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int MOD = 1e9 + 7;
    
    int qpow(ll x, int n) {
        ll res = 1;
        while(n) {
            if(n & 1)
                res = res * x % MOD;
            x = x * x % MOD;
            n >>= 1;
        }
        return res;
    }
    
    const int MAXN = 5e7 + 500;
    
    int G[MAXN];
    int p[3100000], ptop;
    //int pk[MAXN]
    bool np[MAXN];
    int N, L, R;
    
    void sieve(int n) {
        G[0] = 0;
        G[1] = 1;
        //pk[1]=1;
        np[1] = 1;
        for(int i = 2; i <= n; i++) {
            if(!np[i]) {
                p[++ptop] = i;
                //pk[i] = i;
                G[i] = qpow(i, N - 2);
            }
            for(int j = 1, t; j <= ptop && (t = i * p[j]) <= n; j++) {
                np[t] = 1;
                if(i % p[j]) {
                    //pk[t] = p[j];
                    G[t] = 1ll * G[i] * G[p[j]] % MOD;
                } else {
                    //pk[t] = pk[i] * p[j];
                    //下面是积性
                    /*if(pk[t] == t) {
                        G[t] = qpow(N - t, N - 2);
                    } else {
                        G[t] = 1ll * G[pk[t]] * G[t / pk[t]] % MOD;
                    }*/
                    //其实G[i]是完全积性
                    G[t] = 1ll * G[i] * G[p[j]] % MOD;
                    break;
                }
            }
        }
        //printf("%d
    ",ptop);
        /*for(int i = 1; i <= N; ++i) {
            F[i] = G[N - i];
            //printf("F[%d]=%d
    ", i, F[i]);
        }*/
        /*reverse(G, G + N + 1);
        for(int i = 1; i <= N; ++i) {
            G[i] += G[i - 1];
            if(G[i]>=MOD)
                G[i]-=MOD;
            //printf("F[%d]=%d
    ", i, F[i]);
        }*/
    }
    
    int main() {
    #ifdef Yinku
        freopen("Yinku.in", "r", stdin);
    #endif // Yinku
        while(~scanf("%d%d%d", &N, &L, &R)) {
            if(N <= 2) {
                printf("%d
    ", R - L + 1);
                continue;
            }
            sieve(N);
            int ANS = 0;
            for(int i = N - R; i <= N - L; ++i) {
                ANS += G[i];
                if(ANS >= MOD)
                    ANS -= MOD;
            }
            printf("%d
    ", 1ll * ANS * qpow(qpow(N, N - 2), MOD - 2) % MOD);
        }
        return 0;
    }
    
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int MOD = 1e9 + 7;
    
    int qpow(ll x, int n) {
        ll res = 1;
        while(n) {
            if(n & 1)
                res = res * x % MOD;
            x = x * x % MOD;
            n >>= 1;
        }
        return res;
    }
    
    const int MAXN = 5e7 + 5;
    
    int G[MAXN];
    int p[3100000], ptop;
    int N, L, R;
    
    void sieve(int n) {
        G[0] = 0;
        G[1] = 1;
        for(int i = 2; i <= n; i++) {
            if(!G[i]) {
                p[++ptop] = i;
                G[i] = qpow(i, N - 2);
            }
            for(int j = 1, t; j <= ptop && (t = i * p[j]) <= n; j++) {
                G[t] = 1ll * G[i] * G[p[j]] % MOD;
                if(!(i % p[j]))
                    break;
            }
        }
    }
    
    int main() {
    #ifdef Yinku
        freopen("Yinku.in", "r", stdin);
    #endif // Yinku
        while(~scanf("%d%d%d", &N, &L, &R)) {
            if(N <= 2) {
                printf("%d
    ", R - L + 1);
                continue;
            }
            sieve(N);
            int ANS = 0;
            for(int i = N - R; i <= N - L; ++i) {
                ANS += G[i];
                if(ANS >= MOD)
                    ANS -= MOD;
            }
            printf("%d
    ", 1ll * ANS * qpow(qpow(N, N - 2), MOD - 2) % MOD);
        }
        return 0;
    }
    
  • 相关阅读:
    开始写游戏 --- 第三十一篇
    开始写游戏 --- 第三十篇
    开始写游戏 --- 第二十九篇
    开始写游戏 --- 第二十八篇
    高并发性能调试经验分享
    eclipse调试jdk源码
    synzhronized原理3
    内存屏障
    《JAVA NIO》读书笔记
    并发工具类
  • 原文地址:https://www.cnblogs.com/Yinku/p/11343412.html
Copyright © 2020-2023  润新知