这个题首先是推式子,然后怎么快速的搞定它
首先这个复杂度 n*m<=1e12,我将n分成小于1e6,大于1e6两部分。
先说大于1e6部分,那么m小于1e6,可以o(mlogn)通过。
int ans=0;
for(int i=1; i<=m; i++)
{
ans=(ans+pow(i,n-1))%mod;
}
cout<<ans*n%mod;
这一部分的意思是,我首先确定一个人,只能选最大值,那么选这个人有n种
其次,其余的n-1个人不断的在i(1-m)个数中选。
小于1e6部分,学过拉格朗日插值的知道,复杂度是o(n+1)
可以轻松的套公式解决。
所以此题是第二简单题hh
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod=998244353;
const int N=1e6+10;
int n,m;
int pre[N],suf[N],inv[N],x[N],y[N];
int pow(int x,int n)
{
int res=1;
while(n)
{
if(n&1)res=res*x%mod;
x=x*x%mod;
n>>=1;
}
return res;
}
int lagrange(int n, int *x, int *y, int xi) //求xi点处的f(xi)值
{
int ans = 0;
pre[0] = (xi - x[0]) % mod, suf[n + 1] = 1;
for(int i = 1; i <= n; i ++ ) pre[i] = 1ll * pre[i - 1] * (xi - x[i] + mod) % mod;
for(int i = n; i >= 0; i -- ) suf[i] = 1ll * suf[i + 1] * (xi - x[i]+mod) % mod;
inv[0] = inv[1] = 1;
for(int i = 2; i <= n; i ++ ) inv[i]=inv[mod%i]*(mod-mod/i)%mod;
for(int i = 2; i <= n; i ++ ) inv[i] = 1ll * inv[i] * inv[i - 1] % mod;
for(int i = 0; i <= n; i ++ )
{
ans = (ans + (1ll * y[i] * (i == 0 ? 1 : pre[i - 1])) % mod * suf[i + 1] % mod
* inv[i] % mod * (((n - i) & 1) ? -1 : 1) * inv[n - i] % mod + mod) % mod;
}
return (ans + mod) % mod;
}
signed main()
{
cin>>n>>m;
if(n<=N)
{
for(int i=1;i<=n;i++)
{
x[i]=i;
y[i]=(y[i-1]+pow(i,n-1))%mod;
}
cout<<lagrange(n,x,y,m)*n%mod;
}
else
{
int ans=0;
for(int i=1; i<=m; i++)
{
ans=(ans+pow(i,n-1))%mod;
}
cout<<ans*n%mod;
}
return 0;
}