Educational Codeforces Round 83 (Rated for Div. 2) D

今天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<<"-- "<>n>>m;
  	ll ans=0;
  	for(ll i=2;i

优化后代码

#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<<"-- "<>n>>m;
  	ll ans=0;
  	ll tp;
  	for(ll i=2;i

 

你可能感兴趣的:(CF)