今天CF被D恶心到了,写个题解重新整理下思路,(20开始想,25写完暴力代码,1.30才过,优化后的。。
核心思路就是在暴力的基础上进行组合数等差加速。
C(n-2,i-1)*C(j-1,n-2)*(i-1) __ j: n-1 -> m
我们发现内层循环,每次只是j加一,我们就可以只用一次组合数剩下的用差量表示
对于外层循环同理 只有(i-1) * C(n-2,i-1) i会每次加一。我们也只算一次剩下的用差量表示。
复杂度就降到ON *快速幂log 即可
暴力代码
#include
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
//#define a(i,j) a[(i)*(m+2)+(j)] //m是矩阵的列数
const double PI= acos(-1.0);
const int M = 1e5+7;
/*
int head[M],cnt;
void init(){cnt=0,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt,val;}ee[M*2];
void add(int x,int y,int z){ee[++cnt].nxt=head[x],ee[cnt].to=y,ee[cnt].val=z,head[x]=cnt;}
*/
const ll mod=998244353;
ll qpow(ll a,ll b)
{
ll ans=1;
while(b)
{
if(b&1)ans=ans*a%mod;
a=a*a%mod;
b/=2;
}
return ans;
}
ll C(ll n,ll m)
{
ll ans=1;
for(ll i=1;i<=m;i++)
ans=ans*(n-i+1)%mod;
for(ll i=1;i<=m;i++)
ans=ans*qpow(i,mod-2)%mod;
//cout<<"-- "<<ans<>n>>m;
ll ans=0;
for(ll i=2;i<n;i++)//枚举每个位置为顶点
{
ll tp=C(n-2,i-1);
for(ll j=n-1;j<=m;j++) //顶点的取值
ans=(ans+C(n-2,i-1)*C(j-1,n-2)%mod*(i-1)%mod)%mod;
// cout<<ans<<" "<<i<<endl;
}
cout<<ans<<endl;
return 0;
}
优化后代码
#include
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
//#define a(i,j) a[(i)*(m+2)+(j)] //m是矩阵的列数
const double PI= acos(-1.0);
const int M = 2e5+7;
/*
int head[M],cnt;
void init(){cnt=0,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt,val;}ee[M*2];
void add(int x,int y,int z){ee[++cnt].nxt=head[x],ee[cnt].to=y,ee[cnt].val=z,head[x]=cnt;}
*/
const ll mod=998244353;
ll qpow(ll a,ll b)
{
ll ans=1;
while(b)
{
if(b&1)ans=ans*a%mod;
a=a*a%mod;
b/=2;
}
return ans;
}
ll C(ll n,ll m)
{
ll ans=1;
for(ll i=1;i<=m;i++)
ans=ans*(n-i+1)%mod;
for(ll i=1;i<=m;i++)
ans=ans*qpow(i,mod-2)%mod;
//cout<<"-- "<<ans<>n>>m;
ll ans=0;
ll tp;
for(ll i=2;i<n;i++)//枚举每个位置为顶点
{
if(i==2)
{
tp=C(n-2,i-1);
ll x=C(n-2,n-2);
ll cs=tp*x%mod*(i-1)%mod;
for(ll j=n-1;j<=m;j++) //顶点的取值
{
ans=(ans+cs)%mod;
cs=cs*j%mod*qpow(j-(n-2),mod-2)%mod;
}
tp=ans;
}
else
ans=(ans+tp)%mod;
tp=tp*(n-i-1)%mod*qpow(i-1,mod-2)%mod;
// cout<<ans<<" "<<i<<endl;
}
cout<<ans<<endl;
return 0;
}
作者:夕林山寸