Nowcoder Summer Trainning 6 TF

Nowcoder Summer Trainning 6 TF

题意

定义一棵树的Hash如下:

\[H = (\sum_{i=1}^{n-1}\sum_{j=i+1}^{n}X^iY^jZ^{lca(i,j)})mod\ P(P=998244353) \]

给定F(T)、X、Y和Z,构造一棵树的Hash值为F(T).

题解

构造方案如下:

取37个点,每个点的父节点先设置为1,这样可以计算出一个Hash值为H0.

下面做调整,将后36个点分为6组,每组可以选择一个点z作为父节点,选取另外两个点x,y,将这两个点的父节点设置为z,这样有\((6*C(5,2))^6=90^6\)种方案,每种方案对答案有影响为del。而由于X、Y、Z都是随机生成的,相当于随机了\(90^6\)个调整方案,在本题数域范围[0, P]内与我们答案F(T)碰撞概率极大。

这样问题转化为了:在6组,每组90个数中取一个数,使他们和为F(T)-H0.

采用meet in middle减少枚举量。

分成前三组和后三组,枚举前三组之和记录到map里,再枚举后三组之和在map中寻找碰撞。

代码

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define endl '\n'
const int MAXN = 0;
const double eps = 1e-6;
const LL MOD = 998244353;
LL FT, X, Y, Z;
LL H0 = 0;
LL fast_pow(LL a, LL b)
{
    LL res = 1;
    while (b)
    {
        if (b & 1)
            res = res * a % MOD;
        b >>= 1;
        a = a * a % MOD;
    }
    return res;
}
struct node 
{
    LL x1, y1, z1, x2, y2, z2, x3, y3, z3;
};
map<LL, node> mp;
node ans1, ans2;
void solve()
{
    mp.clear();
    H0 = 0;
    cin >> FT >> X >> Y >> Z;
    for (int i = 1; i <= 36; ++i)
        for (int j = i + 1; j <= 37; ++j)
            H0 = (H0 + fast_pow(X, i) * fast_pow(Y, j) % MOD * Z % MOD) % MOD;
    for (int z1 = 2; z1 <= 7; ++z1)
        for (int x1 = 2; x1 <= 6; ++x1)
            if (x1 != z1)
                for (int y1 = x1 + 1; y1 <= 7; ++y1)
                    if (y1 != z1)
                        
                        for (int z2 = 2; z2 <= 7; ++z2)
                            for (int x2 = 2; x2 <= 6; ++x2)
                                if (x2 != z2)
                                    for (int y2 = x2 + 1; y2 <= 7; ++y2)
                                        if (y2 != z2)

                                            for (int z3 = 2; z3 <= 7; ++z3)
                                                for (int x3 = 2; x3 <= 6; ++x3)
                                                    if (x3 != z3)
                                                        for (int y3 = x3 + 1; y3 <= 7; ++y3)
                                                            if (y3 != z3)
                                                            {
                                                                LL del = fast_pow(X, x1) * fast_pow(Y, y1) % MOD * (fast_pow(Z, z1) - Z) % MOD;
                                                                del += fast_pow(X, x2 + 6) * fast_pow(Y, y2 + 6) % MOD * (fast_pow(Z, z2 + 6) - Z) % MOD;
                                                                del += fast_pow(X, x3 + 12) * fast_pow(Y, y3 + 12) % MOD * (fast_pow(Z, z3 + 12) - Z) % MOD;
                                                                if (z1 < x1)
                                                                    del += fast_pow(X, z1) * fast_pow(Y, x1) % MOD * (fast_pow(Z, z1) - Z) % MOD;
                                                                else
                                                                    del += fast_pow(X, x1) * fast_pow(Y, z1) % MOD * (fast_pow(Z, z1) - Z) % MOD;
                                                                if (z2 < x2)
                                                                    del += fast_pow(X, z2 + 6) * fast_pow(Y, x2 + 6) % MOD * (fast_pow(Z, z2 + 6) - Z) % MOD;
                                                                else
                                                                    del += fast_pow(X, x2 + 6) * fast_pow(Y, z2 + 6) % MOD * (fast_pow(Z, z2 + 6) - Z) % MOD;
                                                                if (z3 < x3)
                                                                    del += fast_pow(X, z3 + 12) * fast_pow(Y, x3 + 12) % MOD * (fast_pow(Z, z3 + 12) - Z) % MOD;
                                                                else
                                                                    del += fast_pow(X, x3 + 12) * fast_pow(Y, z3 + 12) % MOD * (fast_pow(Z, z3 + 12) - Z) % MOD;
                                                                
                                                                if (z1 < y1)
                                                                    del += fast_pow(X, z1) * fast_pow(Y, y1) % MOD * (fast_pow(Z, z1) - Z) % MOD;
                                                                else
                                                                    del += fast_pow(X, y1) * fast_pow(Y, z1) % MOD * (fast_pow(Z, z1) - Z) % MOD;
                                                                if (z2 < y2)
                                                                    del += fast_pow(X, z2 + 6) * fast_pow(Y, y2 + 6) % MOD * (fast_pow(Z, z2 + 6) - Z) % MOD;
                                                                else
                                                                    del += fast_pow(X, y2 + 6) * fast_pow(Y, z2 + 6) % MOD * (fast_pow(Z, z2 + 6) - Z) % MOD;
                                                                if (z3 < y3)
                                                                    del += fast_pow(X, z3 + 12) * fast_pow(Y, y3 + 12) % MOD * (fast_pow(Z, z3 + 12) - Z) % MOD;
                                                                else
                                                                    del += fast_pow(X, y3 + 12) * fast_pow(Y, z3 + 12) % MOD * (fast_pow(Z, z3 + 12) - Z) % MOD;
                                                                del = ((del % MOD) + MOD) % MOD;
                                                                mp[del] = (node){x1, y1, z1, x2 + 6, y2 + 6, z2 + 6, x3 + 12, y3 + 12, z3 + 12};
                                                            }
    
    for (int z1 = 2; z1 <= 7; ++z1)
        for (int x1 = 2; x1 <= 6; ++x1)
            if (x1 != z1)
                for (int y1 = x1 + 1; y1 <= 7; ++y1)
                    if (y1 != z1)
                        
                        for (int z2 = 2; z2 <= 7; ++z2)
                            for (int x2 = 2; x2 <= 6; ++x2)
                                if (x2 != z2)
                                    for (int y2 = x2 + 1; y2 <= 7; ++y2)
                                        if (y2 != z2)

                                            for (int z3 = 2; z3 <= 7; ++z3)
                                                for (int x3 = 2; x3 <= 6; ++x3)
                                                    if (x3 != z3)
                                                        for (int y3 = x3 + 1; y3 <= 7; ++y3)
                                                            if (y3 != z3)
                                                            {
                                                                LL del = fast_pow(X, x1 + 18) * fast_pow(Y, y1 + 18) % MOD * (fast_pow(Z, z1 + 18) - Z) % MOD;
                                                                del += fast_pow(X, x2 + 24) * fast_pow(Y, y2 + 24) % MOD * (fast_pow(Z, z2 + 24) - Z) % MOD;
                                                                del += fast_pow(X, x3 + 30) * fast_pow(Y, y3 + 30) % MOD * (fast_pow(Z, z3 + 30) - Z) % MOD;
                                                                if (z1 < x1)
                                                                    del += fast_pow(X, z1 + 18) * fast_pow(Y, x1 + 18) % MOD * (fast_pow(Z, z1 + 18) - Z) % MOD;
                                                                else
                                                                    del += fast_pow(X, x1 + 18) * fast_pow(Y, z1 + 18) % MOD * (fast_pow(Z, z1 + 18) - Z) % MOD;
                                                                if (z2 < x2)
                                                                    del += fast_pow(X, z2 + 24) * fast_pow(Y, x2 + 24) % MOD * (fast_pow(Z, z2 + 24) - Z) % MOD;
                                                                else
                                                                    del += fast_pow(X, x2 + 24) * fast_pow(Y, z2 + 24) % MOD * (fast_pow(Z, z2 + 24) - Z) % MOD;
                                                                if (z3 < x3)
                                                                    del += fast_pow(X, z3 + 30) * fast_pow(Y, x3 + 30) % MOD * (fast_pow(Z, z3 + 30) - Z) % MOD;
                                                                else
                                                                    del += fast_pow(X, x3 + 30) * fast_pow(Y, z3 + 30) % MOD * (fast_pow(Z, z3 + 30) - Z) % MOD;
                                                                
                                                                if (z1 < y1)
                                                                    del += fast_pow(X, z1 + 18) * fast_pow(Y, y1 + 18) % MOD * (fast_pow(Z, z1 + 18) - Z) % MOD;
                                                                else
                                                                    del += fast_pow(X, y1 + 18) * fast_pow(Y, z1 + 18) % MOD * (fast_pow(Z, z1 + 18) - Z) % MOD;
                                                                if (z2 < y2)
                                                                    del += fast_pow(X, z2 + 24) * fast_pow(Y, y2 + 24) % MOD * (fast_pow(Z, z2 + 24) - Z) % MOD;
                                                                else
                                                                    del += fast_pow(X, y2 + 24) * fast_pow(Y, z2 + 24) % MOD * (fast_pow(Z, z2 + 24) - Z) % MOD;
                                                                if (z3 < y3)
                                                                    del += fast_pow(X, z3 + 30) * fast_pow(Y, y3 + 30) % MOD * (fast_pow(Z, z3 + 30) - Z) % MOD;
                                                                else
                                                                    del += fast_pow(X, y3 + 30) * fast_pow(Y, z3 + 30) % MOD * (fast_pow(Z, z3 + 30) - Z) % MOD;
                                                                del = ((del % MOD) + MOD) % MOD;
                                                                del = (FT - H0 - del + MOD + MOD) % MOD;
                                                                if (mp.count(del))
                                                                {
                                                                    ans1 = mp[del];
                                                                    ans2 = (node){x1 + 18, y1 + 18, z1 + 18, x2 + 24, y2 + 24, z2 + 24, x3 + 30, y3 + 30, z3 + 30};
                                                                    return;
                                                                }
                                                            }
}
int main()
{
    ios::sync_with_stdio(false);
    cout.tie(NULL);
    int T = 1;
    cin >> T;
    while (T--)
    {
        solve();
        cout << 37 << '\n';
        for (int i = 2; i <= 37; ++i)
            if (i != ans1.x1 && i != ans1.x2 && i != ans1.x3 && i != ans1.y1 && i != ans1.y2 && i != ans1.y3
                && i != ans2.x1 && i != ans2.x2 && i != ans2.x3 && i != ans2.y1 && i != ans2.y2 && i != ans2.y3)
                    cout << 1 << ' ' << i << '\n';
        cout << ans1.z1 << ' ' << ans1.x1 << '\n';
        cout << ans1.z1 << ' ' << ans1.y1 << '\n';
        cout << ans1.z2 << ' ' << ans1.x2 << '\n';
        cout << ans1.z2 << ' ' << ans1.y2 << '\n';
        cout << ans1.z3 << ' ' << ans1.x3 << '\n';
        cout << ans1.z3 << ' ' << ans1.y3 << '\n';

        cout << ans2.z1 << ' ' << ans2.x1 << '\n';
        cout << ans2.z1 << ' ' << ans2.y1 << '\n';
        cout << ans2.z2 << ' ' << ans2.x2 << '\n';
        cout << ans2.z2 << ' ' << ans2.y2 << '\n';
        cout << ans2.z3 << ' ' << ans2.x3 << '\n';
        cout << ans2.z3 << ' ' << ans2.y3 << '\n';
    }
    return 0;
}
posted @ 2022-08-11 16:16  cacu  阅读(14)  评论(0编辑  收藏  举报