首页 > 其他分享 >【未完善】多项式全家桶

【未完善】多项式全家桶

时间:2023-11-26 16:56:48浏览次数:25  
标签:std 完善 CC 多项式 全家 arr len u32 ans

#include <iostream>
#include <cmath>
#include <cctype>
#include <functional>
#include <algorithm>
#include <vector>
#define UP(i,s,e) for(auto i=s; i<e; ++i)
#define DOWN(i,e,s) for(auto i=e; i-->s; )
using std::cin; using std::cout;
using u32 = unsigned int;
using u64 = unsigned long long;
constexpr u32 MOD = 998244353, G = 3, TIM = 23;
template<typename T, typename U>
constexpr T qpow(T x, U tim){
    T ans = 1;
    while(tim){
        if(tim & 1) ans *= x;
        x *= x;
        tim >>= 1;
    }
    return ans;
}
struct m32{
    u32 val;
    m32(){}
    constexpr m32(u32 x):val(x){}
    constexpr bool operator==(m32 b){ return val == b.val; }
    constexpr m32 operator+=(m32 b){ val += b.val; val %= MOD; return *this;}
    constexpr m32 operator*=(m32 b){ val = (u64)val * b.val % MOD; return *this;}
    constexpr m32 operator-=(m32 b){ val += MOD-b.val; val %= MOD; return *this;}
#define ADDOP(op) constexpr m32 operator op(m32 b){ m32 tmp = *this; return tmp op##= b; }
    ADDOP(+);
    ADDOP(-);
    ADDOP(*);
};
using CC = m32;
constexpr u32 bitceil(u32 x){ return x <= 2 ? 2u : (2u << std::__lg(x-1)); }
namespace Poly{ // }{{{
constexpr CC ROOT = qpow(CC(G), (MOD-1)>>TIM), INVROOT = qpow(ROOT, MOD-2);
template<typename T>
void change(T* arr, int len){
    static std::vector<u32> rev;
    if((int)rev.size() != len){
        rev.resize(len);
        rev[0] = 0;
        UP(i, 1, len){
            rev[i] = rev[i>>1] >> 1;
            if(i&1) rev[i] |= len>>1;
        }
    }
    UP(i, 0, len) if((u32)i < rev[i]) std::swap(arr[i], arr[rev[i]]);
}
void ntt(CC* arr, u32 len, bool idft){
    change(arr, len);
    for(u32 l=2; l<=len; l<<=1){
        CC wn = qpow(idft ? INVROOT : ROOT, (1<<TIM)/l);
        for(u32 st=0; st<len; st+=l){
            CC w = 1;
            UP(j, st, st+l/2){
               CC u = arr[j], v = arr[j+l/2]; v *= w;
               arr[j] = u+v; arr[j+l/2] = u-v;
               w *= wn;
            }
        }
    }
    if(idft){
        CC invlen = qpow(CC(len), MOD-2);
        UP(i, 0u, len) arr[i] *= invlen;
    }
}
using newton_method_func_type = std::function<void(CC*, CC*, u32)>;
using newton_method_edge_type = std::function<CC(CC)>;
void newtons_method_recursive(CC *arr, u32 len, std::vector<CC> &ans, std::vector<CC> &tmp, newton_method_func_type &func, newton_method_edge_type &edge){
    if(len == 1){
        ans.clear();
        ans.push_back(edge(arr[0]));
        return;
    }
    newtons_method_recursive(arr, len/2, ans, tmp, func, edge);
    ans.resize(len*2);
    std::fill(ans.begin()+len/2, ans.end(), 0);
    tmp.resize(len*2);
    std::copy(arr, arr+len, tmp.begin());
    std::fill(tmp.begin()+len, tmp.end(), 0);
    func(ans.data(), tmp.data(), len*2);
}
inline void newtons_method(CC *arr, u32 len, std::vector<CC> &ans, newton_method_func_type &func, newton_method_edge_type &edge){
    std::vector<CC> tmp;
    ans.reserve(len*2);
    tmp.reserve(len*2);
    newtons_method_recursive(arr, len, ans, tmp, func, edge);
    ans.resize(len);
}
void polymul(CC *a, CC *b, u32 len){
    ntt(a, len, false);
    ntt(b, len, false);
    UP(i, 0u, len) a[i] *= b[i];
    ntt(a, len, true);
}
void polyinv(CC *arr, u32 len, std::vector<CC> &ans){
    static newton_method_func_type func = [](CC *a, CC *b, u32 len){ 
        ntt(a, len, false);
        ntt(b, len, false);
        UP(i, 0u, len) a[i] *= (CC(2) - a[i] * b[i]);
        ntt(a, len, true);
    };
    static newton_method_edge_type edge = [](CC a){
        return qpow(a, MOD-2);
    };
    newtons_method(arr, len, ans, func, edge);
}
void integrate(CC *arr, u32 len){
    DOWN(i, len, 1u) arr[i] = arr[i-1] * qpow(CC(i), MOD-2);
    arr[0] = 0;
}
void derivative(CC *arr, u32 len){
    UP(i, 0u, len-1) arr[i] = arr[i+1] * CC(i+1);
    arr[len-1] = 0;
}
void polyln(CC *arr, u32 len, std::vector<CC> &ans){
    std::vector<CC> tmp;
    ans.reserve(len*2);
    tmp.resize(len*2);
    std::copy(arr, arr+len, tmp.begin());
    polyinv(arr, len, ans);
    ans.resize(len*2);
    derivative(tmp.data(), len);
    std::fill(ans.begin()+len, ans.end(), 0);
    std::fill(tmp.begin()+len, tmp.end(), 0);
    polymul(ans.data(), tmp.data(), len*2);
    ans.resize(len);
    integrate(ans.data(), len);
}
void polyexp(CC *arr, u32 len, std::vector<CC> &ans){
    static newton_method_func_type func = [](CC *a, CC *b, u32 len){
        std::vector<CC> ln_a;
        polyln(a, len/2, ln_a);
        ln_a.resize(len);
        std::fill(ln_a.begin()+len/2, ln_a.end(), 0);
        ntt(a, len, false);
        ntt(b, len, false);
        ntt(ln_a.data(), len, false);
        UP(i, 0u, len){
            a[i] *= (CC(1) + b[i] - ln_a[i]);
        }
        ntt(a, len, true);
    };
    static newton_method_edge_type edge = [](CC a){ return 1; };
    newtons_method(arr, len, ans, func, edge);
}
void polyqpow(CC *arr, u32 len, std::vector<CC> &ans, u32 tim, u32 tim_phi, bool k_gt_n){
    // tim % MOD, tim % phi(MOD), tim > len
    u32 min_tim = -1u;
    UP(i, 0u, len) if(!(arr[i] == 0)) {
        min_tim = i;
        break;
    }
    if(min_tim == -1u || min_tim * 1llu * tim >= len || (min_tim && k_gt_n)){
        ans.resize(len);
        std::fill(ans.begin(), ans.end(), 0);
        return;
    }
    u32 ktim = min_tim * tim;
    CC scale = arr[min_tim], invscale = qpow(scale, MOD-2), kscale = qpow(scale, tim_phi);
    u32 nlen = bitceil(len - ktim);
    UP(i, 0u, len-min_tim){
        arr[i] = arr[i+min_tim] * invscale;
    }
    UP(i, len-min_tim, len) arr[i] = 0;
    polyln(arr, nlen, ans);
    UP(i, 0u, nlen) arr[i] = ans[i] * tim;
    polyexp(arr, nlen, ans);
    UP(i, 0u, nlen) ans[i] *= kscale;
    ans.resize(len);
    DOWN(i, len, ktim){
        ans[i] = ans[i-ktim];
    }
    UP(i, 0u, ktim) ans[i] = 0;
}
} // {}}}

标签:std,完善,CC,多项式,全家,arr,len,u32,ans
From: https://www.cnblogs.com/x383494/p/17857527.html

相关文章

  • 算法学习笔记(41): 朴素多项式算法
    朴素多项式算法-\(O(n^2)\)合集我们并不需要NTT,就算需要,也只是用来优化乘法。多项式求逆对于多项式\(\suma_ix^i\)我们需要构造出一个多项式\(\sumb_ix^i\)使得:\[\begin{cases}a_0b_0=1\\\sum_{i=0}^ka_ib_{k-i}=0&k\ge1\end{cases}\]首先\(......
  • pp_orange的多项式模板
    /*Codebypp_orange*/#include<bits/stdc++.h>#definem_p(a,b)make_pair(a,b)#definepbpush_back#definelllonglong#defineullunsignedlonglong#definelldlongdouble#defineinf0x7FFFFFFF#defineinff9223372036854775807#definerep(i,l,......
  • 苹果电脑 Adobe2023 全家桶 Mac 直装版 最新下载安装
    每一个软件都是亲测上传,都是目前最新的,简化了安装流程适用于小白,全部都是无脑直接安装。Adobe2023全家桶直装版更新日期2023-06-11,包含:AdobeIllustrator、AdobeAcrobatProDC、AdobePremierePro、AdobeAudition、AdobePhotoshop、LightroomClassic、AdobeAfter......
  • Aignize第一期完善产品逻辑+类图说明书
    Aiganize产品说明+拟类图(第一期)·附图: 此应用由:前端:微信小程序前端+vue3后台管理系统后端:Springboot+Mysql服务器:后端服务器+AI交互服务器整个应用流程大致分为:活动|聊天|AI影子交互|三个模块用户在刚进入小程序未注册登录时:为游客注册登录后为用户,可申请为组局者用户逻辑如......
  • Switch选择结构 反编译待完善
     ......
  • JavaDoc生成文档(待完善)
    使用IDEA产生Java.doc文档在网摘点赞里  命令行:javadoc-encoding UTF-8-charsetUTF-8Doc.java(文件名)    ......
  • 为zabbix_server_docker容器安装Python 3完善机器人告警脚本环境
    1.安装Python3dnfinstallpython3 2.要验证安装,请输入以下命令检查Python版本:python3--version 3.建立软连接:ln-s/usr/bin/python3.6/usr/bin/python  4.安装epel:dnfinstallpython3-devel-y 5.启用epel:dnfins......
  • 亚马逊云科技如何完善自动机器人及大语言模型的问答回复准确度
     概述 客户联络中心在现代是构成一个完整企业的重要组成部分,作为企业与顾客的连接纽带,在销售、服务支持以及提升顾客满意度方面发挥着至关重要的作用。使用亚马逊云科技AmazonConnect出海企业可以快速搭建自己的全球客服联络中心。当前客服联络中心也面临诸多的挑战,如长时间的电......
  • 4.Sklearn多项式回归
    1.多项式回归介绍在一元回归分析中,如果依变量y与自变量X的关系为非线性的,但是又找不到适当的函数曲线来拟合,则可以采用一元多项式回归多项式回归的最大优点就是可以通过增加X的高次项对实测点进行逼近,直至满意为止。事实上,多项式回归可以处理相当一类非线性问题,它在回归分析中......
  • Kali基础工具使用(完善中)
    Kali是什么 Kali是一款集成了各种专业工具的渗透测试的基于Debian的Linux操作系统Kali中包含600多款工具软件,适用于各种信息安全和渗透测试研究 Kali的安装 参考:虚拟机VMware下载与安装教程(详细)_vmware虚拟机-CSDN博客【2022最新KaliLinux安装教程【附安装......