P9816 少项式复合幂题解
P9816 少项式复合幂题解
题目传送门
35 分做法
先注意题目加粗的字,提示我们应该考虑
预处理
显然
查询操作
直接一次一次跳,暴力跳
代码
#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;
}
100 分做法
可以发现查询操作若为
预处理
用
查询操作
把
代码
#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;
}