2025牛客多校第八场 根号-2进制 个人题解

J.根号-2进制

数学 #FFT

思路

赛后发现身边的同学都是通过借位来解决进位问题的,在此提供一种全程不出现减法的顺推做法

首先\(A,B\)可以理解为两个多项式:\(A_{0}+A_{1}\sqrt{ -2 }+A_{2}(\sqrt{ -2 })^2+\dots\),其中\(A_{i}=\{ 0,1 \}\),\(B_{i}\)同理

那么可以使用多项式乘法\(FFT\)先将\(A,B\)相乘后的结果表示为一个新的多项式\(C\),此时该多项式的系数\(C_{i}\)不一定为\(\{ 0,1 \}\)

因此我们的任务变为了如何将一个多项式的系数在\(\sqrt{ -2 }\)进制下全部化为\(\{ 0,1 \}\)

为了方便观察,将\(\sqrt{ -2 }\)写为\(2^{\frac{1}{2}}i\),则\((\sqrt{ -2 })^k=2^{\frac{k}{2}}i^k\)

打表观察:

\[\begin{align} &i=1:\quad 2^{\frac{1}{2}}i\\ \\ &i=2:\quad -2^{\frac{2}{2}}\\ \\ &i=3:\quad -2^{\frac{3}{2}}i \\ \\ &i=4:\quad 2^{\frac{4}{2}}\\ \\ &i=5:\quad 2^{\frac{5}{2}}i\\ \\ &i=6:\quad -2^{\frac{6}{2}} \end{align} \]

发现明显规律且周期\(T=4\)

设\(a=\sqrt{ -2 }\),则必有\(2^2\times a^p=a^{p+4}\)

进一步推广:

\[2^{2k}\times a^p=a^{p+4k} \]

现在解决了\(2\)的偶数次幂与\(a\)的任意次幂相乘的递推,如果能够解决\(2\)的奇数次幂与\(a\)任意次幂相乘的递推,那么就可以通过对多项式系数\(C_{i}\)二进制分解 不断递推,将所有系数化为\(\{ 0,1 \}\)

由于\(2^{2k+1}=2^{2k}\times 2\),因此解决\(2\times a^p\)的递推即可

观察表格可知\(2\times a^p=-a^{p+2}\),即\(2\times a^p+a^{p+2}=0\)

因此有\(2\times a^p+a^{p+2}=2\times a^{p+2}+a^{p+4}=0\)

则有:

\[2\times a^p=a^{p+2}+a^{p+4} \]

这样就能不断地将系数向高次推推推,最终全部推成\(\{ 0,1 \}\)啦!

然而,聪明的\(phaethon 90\)发现了问题:

如果原本的多项式在推导过程中包含形如\(2\times a^p+a^{p+2}+\dots\)的部分,那么对\(2\times a^p\)套用上述递推将导致无限循环,因为\(2\times a^p+a^{p+2}=0\)

因此,在使用第二个递推前,先判断\(a^{p+2}\)项的系数是否为奇数:

  • 如果为奇数,那么就可以利用\(2\times a^p+a^{p+2}=0\)将这个奇数消去,避免在处理到\(p+2\)位时仍然是个奇数
  • 如果为偶数,那么可以利用递推二\(2\times a^p=a^{p+2}+a^{p+4}\)往高位推

当更新过的最高位已经与当前位重合了,那么就退出循环

fun fact:这个代码在赛事实际上早就写好了,但是因为不知道如何给FFT清空,以及没有发现最后输出的多项式的项数size远大于size(A)+size(B),导致没有清空完全,一直在WAAAAA

代码实现

cpp 复制代码
#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<queue>
#include<cmath>
#include<unordered_map>
#include<numeric>
using namespace std;
using ll = long long;
#define rep(i, a, b) for(ll i = (a); i <= (b); i ++)
#define per(i, a, b) for(ll i = (a); i >= (b); i --)
#define see(stl) for(auto&ele:stl)cout<<ele<<" "; cout<<'\n';
constexpr ll inf = 1e9 + 5;
#define int ll
#define double long double
constexpr ll  mod = 998244353;

const double pi = acos(-1);

const int N = 4e5 + 5;

struct complex {
    double x, y;
    complex operator+(const complex& t)const {
        return{ x + t.x,y + t.y };
    }
    complex operator-(const complex& t)const {
        return{ x - t.x,y - t.y };
    }
    complex operator*(const complex& t)const {
        return{ x * t.x - y * t.y,x * t.y + y * t.x };
    }
}A[N], B[N];
int R[N];

void FFT(complex A[], int n, int op) {
    rep(i, 0, n - 1)R[i] = R[i / 2] / 2 + ((i & 1) ? n / 2 : 0);
    rep(i, 0, n - 1)if (i < R[i])swap(A[i], A[R[i]]);
    for (int i = 2; i <= n; i <<= 1) {
        complex w1({ cos(2 * pi / i),sin(2 * pi / i) * op });
        for (int j = 0; j < n; j += i) {
            complex wk({ 1,0 });
            rep(k, j, j + i / 2 - 1) {
                complex x = A[k], y = A[k + i / 2] * wk;
                A[k] = x + y; A[k + i / 2] = x - y;
                wk = wk * w1;
            }
        }
    }
}
int n = 0, m = 0,pos=0;
int ans[N+10];
void eachT() {
    string s1, s2; cin >> s1 >> s2;
    int up=max(n,m);
    up=max(up,pos);
    rep(i, 0, up+5) {
        A[i] = B[i] = { 0,0 };
        R[i] =ans[i]=0;
    }
    n = s1.length() - 1, m = s2.length() - 1;
    rep(i, 0, n)A[i].x = s1[n - i] - '0', A[i].y = 0;
    rep(i, 0, m)B[i].x = s2[m - i] - '0', B[i].y = 0;
    for (m = n + m, n = 1; n <= m; n <<= 1);
    FFT(A, n, 1); FFT(B, n, 1);
    rep(i, 0, n - 1)A[i] = A[i] * B[i];
    FFT(A, n, -1);
    int highid = 0;
    bool all0 = 1;
    rep(i, 0, m) {
        ans[i] = (int)(A[i].x / n + 0.5);
        if (ans[i] != 0)all0 = 0;
        if (ans[i] > 0 && i > highid) {
            highid = i;
        }
    }
    if (all0) {
        cout << 0 << '\n';
        return;
    }

    pos = 0;
    while (1) {
        int k = ans[pos], cnt = 0;
        ans[pos] = (k & 1);
        k >>= 1;
        while (k) {
            cnt++;//2^cnt
            if (k & 1) {
                if (cnt % 2 == 0) {//2^2k
                    ans[pos + 4 * cnt / 2];
                    ans[pos + 4 * cnt / 2]++;
                    highid=max(highid,pos + 4 * cnt / 2);
                }
                else {
                    if (cnt / 2 == 0) {//2^1
                        if (ans[pos + 2] % 2 == 0) {
                            ans[pos + 4];
                            ans[pos + 4] += 1;
                            ans[pos + 2] += 1;
                            highid=max(highid,pos + 4);
                        }
                        else {
                            ans[pos + 2] -= 1;
                            highid=max(highid,pos + 2);
                        }
                    }
                    else {//2^2k+1
                        ans[pos + cnt / 2 * 4];
                        ans[pos + cnt / 2 * 4] += 2;
                        highid=max(highid,pos + cnt / 2 * 4);
                    }
                }
            }
            k >>= 1;
        }
        if (pos == highid)break;
        pos++;
    }
    int st = pos;
    per(i, pos, 0){
        if (ans[i] != 0){
            st = i;break;
        }
    }
    if(st==pos&&ans[pos]==0){
        cout<<0<<'\n';return;
    }
    per(i, st, 0)cout << ans[i];
    cout << '\n';
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    ll t = 1;
    cin >> t;
    while (t--) {
        eachT();
    }
}
相关推荐
CUC-MenG7 小时前
2025牛客多校第七场 双生、象牙 个人题解
数学·gcd·欧拉筛·质数筛
zhmc2 天前
欧拉公式的意义
数学·应用数学
CUC-MenG5 天前
快速莫比乌斯变换(FMT)与莫比乌斯反演 例题:树上lcm
数学·dfs·fmt
CUC-MenG6 天前
2025牛客多校第五场 K.完美旅程 J.最快覆盖问题 E.神秘异或操作 个人题解
数学·dfs·bfs·优先队列·二分·位运算·fmt·曼哈顿距离·fwt
民乐团扒谱机7 天前
【微实验】MATLAB频谱 三维可视化
matlab·信号·fft·频谱·傅里叶变换·stft·语谱图
Always_away8 天前
26考研|数学分析:重积分
笔记·学习·考研·数学
w909524 天前
【9】斯特林数学习笔记
数学·学习笔记
墨风如雪25 天前
8B 模型吊打 671B?数学证明界“卷王”Goedel-Prover-V2 来了!
数学·aigc
minglie11 个月前
高斯代数基本定理的一种证明
数学