Counting Stars 2023“钉耙编程”中国大学生算法设计超级联赛(5)hdu7335

Problem - 7335

题目大意:如果一个点连接着k个点,就称这k+1个点构成k星图,现给出一个大小为n的图,问2星图的数量^3星图的数量^...^n星图的数量是多少

3<=n<=1e6;1<=m<=1e6

思路:因为边数总共不超过1e6,所以可以遍历点,遍历度数,因为不同星图数量直接要求异或,所以对于每个点,只能求出它对每个星图的贡献,最后再求异或和

//#include<__msvc_all_public_headers.hpp>
#include
using namespace std;
typedef long long ll;
const ll MOD = 1e9+7;
const int N = 1e6 + 5;
ll inv[N], fac[N];
ll C(ll x, ll y)
{//C(x,y)=y!/((y-x)!x!)
    return fac[y] * inv[x] % MOD * inv[y - x] % MOD;
}
ll d[N];
ll cnt[N];
ll qpow(ll a, ll b)
{//快速幂
    ll ret = 1;
    while (b)
    {
        if (b & 1)
        {
            ret = ret * a % MOD;
        }
        a = a * a % MOD;
        b >>= 1;
    }
    return ret;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin >> t;
    fac[0] = 1;
    inv[0] = 1;
    for (ll i = 1; i <= 1000000; i++)
    {//预处理阶乘和阶乘逆元
        fac[i] = (fac[i - 1] * i) % MOD;
        inv[i] = qpow(fac[i], MOD - 2);
    }
    while (t--)
    {
        int n, m;
        cin >> n >> m;
        for (int i = 1; i <= n; i++)
        {
            d[i] = cnt[i] = 0;
        }
        for (int i = 1; i <= m; i++)
        {
            int u, v;
            cin >> u >> v;
            d[u]++;
            d[v]++;
        }
        for (int i = 1; i <= n; i++)
        {
            for (int j = 2; j <= d[i]; j++)
            {
                cnt[j] = (cnt[j] + C(j, d[i])) % MOD;//第i个点对j星图的贡献
            }
        }
        ll ans = 0;
        for (int j = 2; j <= n; j++)
        {
            ans = ans ^ cnt[j];
        }
        cout << ans << endl;
    }
    return 0;
}

你可能感兴趣的:(图论,算法,c++)