1 条题解

  • 0
    @ 2025-8-24 22:52:05

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar znszns
    **

    搬运于2025-08-24 22:52:05,当前版本为作者最后更新于2023-10-30 14:57:47,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    P9816 少项式复合幂题解

    题目传送门

    3535 分做法

    先注意题目加粗的字,提示我们应该考虑 pp 的范围。

    预处理

    显然 f(x)f(xmod p)(mod p)f(x)\equiv f(x\bmod\ p)(\bmod\ p),所以考虑预处理 f(x)modpf(x)\bmod pf(x)=i=1maixbif(x)=\sum_{i=1}^ma_ix^{b_i}xx 范围为 00p1p-1,时间复杂度为 Θ(mplogbi)\Theta(mp\log{bi})

    查询操作

    直接一次一次跳,暴力跳 yy 次找到 fy(x)modpf_y(x)\bmod p,时间复杂度为 Θ(qy)\Theta(qy)

    代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=1e5+10;
    int m,q;
    ll mod,f[N],a[N],b[N];
    ll qpow(ll x,ll y)
    {
    	ll res=1;
    	for(;y;y>>=1,x=x*x%mod)
    	{
    		if(y&1) res=res*x%mod;
    	}
    	return res;
    }
    int main()
    {
    	scanf("%d%d%lld",&m,&q,&mod);
    	for(int i=1;i<=m;i++) scanf("%lld%lld",&a[i],&b[i]);
    	for(int i=0;i<mod;i++)
    	{
    		for(int j=1;j<=m;j++)
    		{
    			f[i]=(f[i]+a[j]*qpow(i,b[j])%mod)%mod;
    		}
    	}
    	ll x,y,ans;
    	for(int i=1;i<=q;i++)
    	{
    		scanf("%lld%lld",&x,&y);
    		ans=f[x%mod];
    		for(int j=2;j<=y;j++)
    		{
    			ans=f[ans];
    		}
    		cout<<ans<<endl;
    	}
    	return 0;
    }
    

    100100 分做法

    可以发现查询操作若为 Θ(qlogy)\Theta(q\log{y}) 是可以过的,于是先求出 yy 的二进制表示,比如说要跳 1010 次,相当于先跳 212^1 次,再跳 232^3 次。

    预处理

    dp(i,j)dp(i,j) 表示 f(x)f(x)2j2^j 次的结果,转移为 dp(i,j)=dp(dp(i,j1),j1)dp(i,j)=dp(dp(i,j-1),j-1)

    查询操作

    yy 用二进制表示,最低位是第 00 位,若第 ii 位为 11,设当前答案为 ansansansans 则跳到 dp(ans,i)dp(ans,i),表示跳了 2i2^i 次,最后输出 ansans 即可。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=1e5+10,M=25;
    int m,q;
    ll mod,f[N][M],a[N],b[N];
    ll qpow(ll x,ll y)
    {
    	ll res=1;
    	for(;y;y>>=1,x=x*x%mod)
    	{
    		if(y&1) res=res*x%mod;
    	}
    	return res;
    }
    int main()
    {
    	scanf("%d%d%lld",&m,&q,&mod);
    	for(int i=1;i<=m;i++) scanf("%lld%lld",&a[i],&b[i]);
    	for(int i=0;i<mod;i++)
    	{
    		for(int j=1;j<=m;j++)
    		{
    			f[i][0]=(f[i][0]+a[j]*qpow(i,b[j])%mod)%mod;
    		}
    	}
    	for(int j=1;j<M;j++)
    	{
    		for(int i=0;i<mod;i++)
    		{
    			f[i][j]=f[f[i][j-1]][j-1];
    		}
    	}
    	ll x,y,ans,cnt;
    	for(int i=1;i<=q;i++)
    	{
    		scanf("%lld%lld",&x,&y);
    		cnt=0;
    		ans=x%mod;
    		while(y)
    		{
    			if(y&1) ans=f[ans][cnt];
    			cnt++;
    			y>>=1;
    		}
    		cout<<ans<<endl;
    	}
    	return 0;
    }
    
    • 1

    信息

    ID
    9325
    时间
    1000ms
    内存
    512MiB
    难度
    4
    标签
    递交数
    0
    已通过
    0
    上传者