首页 > 其他分享 >P9816 少项式复合幂 题解

P9816 少项式复合幂 题解

时间:2024-01-14 12:33:20浏览次数:23  
标签:typedef include 少项 题解 bmod int template P9816 define

题目链接:少项式复合幂

注意到题目的模并不是很大,我们考虑两个核心的性质。

  1. \(f(f(x)) \bmod p=f(f(x) \bmod p) \bmod p\),证明直接代入 \(f(x)\) 进去得到:\(f(f(x))=a_0 \times f^0(x)+a_1\times f^1(x)...+a_n\times f^n(x) \bmod p=\)

\[\sum_{i=0}^{n}a_i \times f^{i}(x) \bmod p=\sum_{i=0}^{n}a_i \times (f^{i}(x) \bmod p) \bmod p,根据模运算的四则运算得证。 \]

  1. \(f_{x_1+x_2}(x)=f_{x_2}(f_{x_1}(x))\),这个很显然,进行 \(x_1\) 次函数迭代以后再进行 \(x_2\) 次函数迭代,总函数迭代次不变。

基于第二点,我们就可以倍增了,基于第一点,我们可以预处理出所有的 \(f(i) \bmod p\),用于第二点的倍增。

倍增实际上就是将一个需要走 \(k\) 步的函数迭代,根据它的二进制分解为走 \(k_1+k_2+k_3...\) 步,而一个数的二进制数不会超过 \(\log{V_{max}}\) 级别。

参考代码
#include <bits/stdc++.h>

//#pragma GCC optimize("Ofast,unroll-loops")

#define isPbdsFile

#ifdef isPbdsFile

#include <bits/extc++.h>

#else

#include <ext/pb_ds/priority_queue.hpp>
#include <ext/pb_ds/hash_policy.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/trie_policy.hpp>
#include <ext/pb_ds/tag_and_trait.hpp>
#include <ext/pb_ds/hash_policy.hpp>
#include <ext/pb_ds/list_update_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/exception.hpp>
#include <ext/rope>

#endif

using namespace std;
using namespace __gnu_cxx;
using namespace __gnu_pbds;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef tuple<int, int, int> tii;
typedef tuple<ll, ll, ll> tll;
typedef unsigned int ui;
typedef unsigned long long ull;
typedef __int128 i128;
#define hash1 unordered_map
#define hash2 gp_hash_table
#define hash3 cc_hash_table
#define stdHeap std::priority_queue
#define pbdsHeap __gnu_pbds::priority_queue
#define sortArr(a, n) sort(a+1,a+n+1)
#define all(v) v.begin(),v.end()
#define yes cout<<"YES"
#define no cout<<"NO"
#define Spider ios_base::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
#define MyFile freopen("..\\input.txt", "r", stdin),freopen("..\\output.txt", "w", stdout);
#define forn(i, a, b) for(int i = a; i <= b; i++)
#define forv(i, a, b) for(int i=a;i>=b;i--)
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
#define endl '\n'
//用于Miller-Rabin
[[maybe_unused]] static int Prime_Number[13] = {0, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37};

template <typename T>
int disc(T* a, int n)
{
    return unique(a + 1, a + n + 1) - (a + 1);
}

template <typename T>
T lowBit(T x)
{
    return x & -x;
}

template <typename T>
T Rand(T l, T r)
{
    static mt19937 Rand(time(nullptr));
    uniform_int_distribution<T> dis(l, r);
    return dis(Rand);
}

template <typename T1, typename T2>
T1 modt(T1 a, T2 b)
{
    return (a % b + b) % b;
}

template <typename T1, typename T2, typename T3>
T1 qPow(T1 a, T2 b, T3 c)
{
    a %= c;
    T1 ans = 1;
    for (; b; b >>= 1, (a *= a) %= c)if (b & 1)(ans *= a) %= c;
    return modt(ans, c);
}

template <typename T>
void read(T& x)
{
    x = 0;
    T sign = 1;
    char ch = getchar();
    while (!isdigit(ch))
    {
        if (ch == '-')sign = -1;
        ch = getchar();
    }
    while (isdigit(ch))
    {
        x = (x << 3) + (x << 1) + (ch ^ 48);
        ch = getchar();
    }
    x *= sign;
}

template <typename T, typename... U>
void read(T& x, U&... y)
{
    read(x);
    read(y...);
}

template <typename T>
void write(T x)
{
    if (typeid(x) == typeid(char))return;
    if (x < 0)x = -x, putchar('-');
    if (x > 9)write(x / 10);
    putchar(x % 10 ^ 48);
}

template <typename C, typename T, typename... U>
void write(C c, T x, U... y)
{
    write(x), putchar(c);
    write(c, y...);
}


template <typename T11, typename T22, typename T33>
struct T3
{
    T11 one;
    T22 tow;
    T33 three;

    bool operator<(const T3 other) const
    {
        if (one == other.one)
        {
            if (tow == other.tow)return three < other.three;
            return tow < other.tow;
        }
        return one < other.one;
    }

    T3() { one = tow = three = 0; }

    T3(T11 one, T22 tow, T33 three) : one(one), tow(tow), three(three)
    {
    }
};

template <typename T1, typename T2>
void uMax(T1& x, T2 y)
{
    if (x < y)x = y;
}

template <typename T1, typename T2>
void uMin(T1& x, T2 y)
{
    if (x > y)x = y;
}

constexpr int N = 1e5 + 10;
constexpr int PMax = 1e5;
int a[N], b[N];
int n, p, q;

inline int f(const ll x)
{
    ll ans = 0;
    forn(i, 1, n)
    {
        ll curr = qPow(x, b[i], p); //快速幂快速算x^b[i]
        ans = (ans + a[i] * curr) % p; //算出a*x^b[i]加上去
    }
    return ans;
}

constexpr int T = ceil(log2(1e7));
int go[N][T + 1]; //倍增预处理

inline void solve()
{
    cin >> n >> q >> p;
    forn(i, 1, n)cin >> a[i] >> b[i];
    forn(i, 0, PMax)go[i][0] = f(i);
    forn(j, 1, T)forn(i, 0, PMax)go[i][j] = go[go[i][j - 1]][j - 1];//倍增预处理
    while (q--)
    {
        int x, y;
        cin >> x >> y;
        x %= p;
        //二进制分解
        while (y)
        {
            int t = log2(y);
            x = go[x][t];
            y -= 1 << t;
        }
        cout << x << endl;
    }
}

signed int main()
{
    Spider
    //------------------------------------------------------
    int test = 1;
    //    read(test);
    // cin >> test;
    forn(i, 1, test)solve();
    //    while (cin >> n, n)solve();
    //    while (cin >> test)solve();
}

\[时间复杂度为 \ O(m\times p\log{b_{max}}+p\log{p}+q\log{y_{max}}) \]

标签:typedef,include,少项,题解,bmod,int,template,P9816,define
From: https://www.cnblogs.com/Athanasy/p/17963540

相关文章

  • P5501 [LnOI2019] 来者不拒,去者不追 题解
    题目链接:来者不拒,去者不追直接在线查询题目所给的式子是很困难的,我们考虑单点考察贡献。对于一个已经确定的式子,我们发现加入一个数或者删除一个数的贡献如图所示:如图所示,在原有的序列为\((1,2,3)\)当中,我们加入新的\(2\)进去,我们观察到每个数的贡献的变化是这样,比\(2\)......
  • 题解 P7169 [eJOI2020 Day1] Exam
    传送门。题意有两个长度为\(N\)的数列\(A_i\),\(B_i\)。可以对\(A\)数组进行若干次操作,每次可以使\(A_i\)到\(A_j\)中的所有数变成期间的最大值,求最多能使多少个数满足要求。分析显然,要使我们的某一个\(A_x\)变成\(B_x\),至少会包含\(A_{L_x}\)或\(A_{R_x}\),\(L_......
  • P5321 [BJOI2019] 送别 题解--zhengjun
    由于大家的做法需要大量分类讨论和代码量,这里提供一种不怎么分类的,容易实现的做法。首先,由于墙体会随时变化,所以直接对墙体本身维护不是很方便。我们可以牺牲一点常数,对\((i,j)\)建立四个点\(UL_{i,j},UR_{i,j},DL_{i,j},DR_{i,j}\)分别表示\((i-\varepsilon,j-\varepsilo......
  • AT_arc125_c [ARC125C] LIS to Original Sequence 题解
    题目传送门前置知识贪心|构造解法对于任意一个未加入序列\(P\)的数\(x<A_{i}(1\lei\lek-1)\),如果其放在了\(A_{i}\)的前面,会导致最长上升子序列长度加一,从而不符合题目要求。因此我们需要把\(x\)放在\(A_{i}\)后面,同理,为符合题目要求,我们仅选择放最小的那一个......
  • P2198 杀蚂蚁 题解
    题目大意有一条长度为\(n\)个单位长度的路,蚂蚁们要从起点走到终点。蚂蚁们每走\(1\)个单位距离需要\(T\)秒钟。现在,出题人可以在路上修筑\(3\)种防御塔来阻挡蚂蚁的进攻,每个单位距离只能修筑\(1\)座塔,塔的作用分别如下:激光塔:蚂蚁在塔前时每秒会受到\(r\)点伤害。......
  • P3243 [HNOI2015] 菜肴制作 题解
    前言今天考试考到这道题,挂惨了。题意有\(n\)道菜肴,编号为\(1\simn\)。有\(m\)个条件,形如\((i,j)\),表示菜肴\(i\)必须在菜肴\(j\)之前制作。需求出一个菜肴的制作顺序,满足:在满足所有限制的前提下,\(1\)号菜肴尽量优先制作。在满足所有限制,\(1\)号菜肴尽量优......
  • P9007 [入门赛 #9] 最澄澈的空与海 (Hard Version) 题解
    Updon2023.10.1408:21:修改了推式子和题意的一些小错误。前言一道恐怖的绿题。显然我认为应该是蓝题。(不过在这篇题解写到一半的时候升蓝了,感谢@StudyingFather。)名字挺好的。题意给定\(n\),求出满足以下条件的三元组\((x,y,z)\)的组数:\(x\ge0,z\ge1\)。\(......
  • AT_abc243_g [ABC243G] Sqrt题解
    题目大意有一个数列,初始时只有一个数\(X\)。你可以对它进行一种操作:设末尾的数为\(Y\),从\(1\sim\sqrt{Y}\)中选一个数加到数列的末尾。如此进行\(10^{100}\)次操作,问数列一共有多少种可能的状态。解法考虑DP。设\(dp_i\)表示以数字\(i\)开头的数列可能的状态。设......
  • CF713D 题解
    题意给一个\(01\)矩阵,多次求在给定区间内最大的全\(1\)正方形边长。思路容易想到二分:先预处理出以每个位置为右下角的最大合法正方形的边长\(mx_{i,j}\),然后对于每个询问,我们二分边长\(mid\),设当前询问的区间左上角为\((x_1,y_1)\),右下角为\((x_2,y_2)\),则能取到\(mi......
  • AT_arc167_e 题解
    题意给定\(k\)和一个排列\(P'\),问有多少个排列\(P\)以最少步数交换相邻两个元素来进行收敛,最终的排列可能是\(P'\),一个排列是收敛的当且仅当对于每一个数,在该数前且比这个数大的数的个数不超过\(k\)个。思路考虑正向的让一个排列收敛,我们设在第\(i\)个位置前且比\(P......