P7116-[NOIP2020] wechat steps [mathematics]

Keywords: Math Luogu

Topic

Title Link: https://www.luogu.com.cn/problem/P7116

General idea of the topic

There is one k k k-dimensional space, second i i The length of dimension i is w i w_i wi, yes n n n steps, each step is the coordinate of a certain dimension + 1 / − 1 +1/-1 +1 / − 1, after each walk n n n steps will start from 1 1 Go again. Now find out how many steps you can take from each point of the space to get out of the space.

1 ≤ n ≤ 5 × 1 0 5 1\leq n\leq 5\times 10^5 1≤n≤5×105

1 ≤ k ≤ 10 , 1 ≤ w i ≤ 1 0 6 1\leq k\leq 10,1\leq w_i\leq 10^6 1 ≤ k ≤ 10,1 ≤ wi ≤ 106 or 1 ≤ k ≤ 3 , 1 ≤ w i ≤ 1 0 9 1\leq k\leq 3,1\leq w_i\leq 10^9 1≤k≤3,1≤wi​≤109

Problem solving ideas

It's obviously troublesome to find the solution to go out at this step, so we can consider finding the number of starting points that haven't gone out after each step, and then finding a sum. And each dimension can be considered separately to a certain extent.

The first round obviously needs special treatment l i , j , r i , j l_{i,j},r_{i,j} li,j, ri,j , denotes the second i i Step after step i j j The minimum displacement (non positive number) and the maximum displacement in j-dimension, then the scheme that won't go out in this step is ∏ j = 1 k ( w j − r i , j + l i , j ) \prod_{j=1}^k (w_j-r_{i,j}+l_{i,j}) Π j=1k (wj − ri,j + li,j), that is, in [ 1 − l , w − r ] [1-l,w-r] [1 − l,w − r] this range can survive, and this can be dealt with violently.

Then consider the second round of each round i i The minimum / maximum displacement distance of step i is still recorded as l i , j , r i , j l_{i,j},r_{i,j} li,j, ri,j, then consider how to calculate how many rounds of each step will die, and record it as t t t.

First set a i a_i ai , indicates the first round of dimensions i i i narrow the scope, and then b i b_i bi , represents the reduced range of this dimension in each subsequent round, then for the second round i i For step i, step j j The longest surviving rounds of the j dimensions are ⌊ a j − r i , j + l i , j b j ⌋ \lfloor\frac{a_j-r_{i,j}+l_{i,j}}{b_j}\rfloor ⌊ bj − aj − ri,j + li,j ⌋, calculate t t After t, suppose that if we can enumerate the rounds, the answer should be
∑ x = 1 t ∏ j = 1 k a j − r i , j + l i , j − b j x \sum_{x=1}^t\prod_{j=1}^ka_j-r_{i,j}+l_{i,j}-b_jx x=1∑t​j=1∏k​aj​−ri,j​+li,j​−bj​x
Obviously O ( k 2 ) O(k^2) O(k2) is multiplied to get a sum x x The polynomials related to x are then summed.

As for polynomial summation, we can ∑ x = 0 t x j \sum_{x=0}^t x^j Σ x=0t and Σ xj are brought into the polynomial explosion, which can be obtained directly by pulling and inserting. Of course, this problem can be applied to k ≤ 3 k\leq 3 In the case of k ≤ 3, we insert polynomials manually, and then k > 3 k>3 k> 3. Just pretreatment directly.

Time complexity: O ( n k 2 ) O(nk^2) O(nk2) or O ( n k 2 + k × m a x { w i } ) O(nk^2+k\times max\{w_i\}) O(nk2+k×max{wi​})

code

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=5e5+10,M=11,P=1e9+7;
ll n,m,ans,pw[M][N*2],l[N][M],r[N][M],w[M],a[M],b[M],e[M],f[M][M];
ll power(ll x,ll b){
	ll ans=1;
	while(b){
		if(b&1)ans=ans*x%P;
		x=x*x%P;b>>=1;
	}
	return ans;
}
ll calc(ll n,ll k){
	if(k>3)return pw[k][n];
	if(k==3)return (n*(n+1)/2%P)*((n*(n+1)/2)%P)%P;
	if(k==2)return n*(n+1)%P*(2*n+1)%P*((P+1)/6)%P;
	if(k==1)return n*(n+1)/2%P; 
	return n+1;
}
signed main()
{
	scanf("%lld%lld",&n,&m);
	for(ll k=4;k<=m;k++)
		for(ll i=1;i<=1e6;i++)
			pw[k][i]=(pw[k][i-1]+power(i,k))%P;
	ans=1;
	for(ll i=1;i<=m;i++)
		scanf("%lld",&w[i]),ans=ans*w[i]%P;
	for(ll i=1;i<=n;i++){
		ll c,d;
		scanf("%lld%lld",&c,&d);e[c]+=d;
		for(ll j=1;j<=m;j++)
			l[i][j]=l[i-1][j],r[i][j]=r[i-1][j];
		l[i][c]=min(l[i][c],e[c]);
		r[i][c]=max(r[i][c],e[c]);
	}
	bool flag=1;
	for(ll i=1;i<=m;i++)
		if(e[i]!=0||w[i]-r[n][i]+l[n][i]<=0)
			{flag=0;break;}
	if(flag)return puts("-1")&0;
	for(ll i=1;i<=n;i++){
		ll sum=1;
		for(ll j=1;j<=m;j++)
			sum=sum*max(0ll,w[j]-r[i][j]+l[i][j])%P;
		ans=(ans+sum)%P;
	}
	for(ll i=1;i<=m;i++)a[i]=w[i]-r[n][i]+l[n][i];
	for(ll i=1;i<=n;i++)
		for(ll j=1;j<=m;j++){
			l[i][j]=min(0ll,l[i][j]+e[j]-l[n][j]);
			r[i][j]=max(0ll,r[i][j]+e[j]-r[n][j]);
		}
	for(ll i=1;i<=m;i++)b[i]=r[n][i]-l[n][i];
	flag=0;
	for(ll i=1;i<=n;i++){
		for(ll j=1;j<=m;j++)f[0][j]=0;
		f[0][0]=1;ll t=1e9+7;
		for(ll j=1;j<=m;j++){
			ll x=a[j]-r[i][j]+l[i][j];
			if(x<=0){flag=1;break;}
			if(b[j]>0)t=min(t,x/b[j]);
			for(ll k=0;k<=m;k++){
				(f[j][k]=f[j-1][k]*x%P)%=P;
				if(k)(f[j][k]+=f[j-1][k-1]*(P-b[j])%P)%=P;
			}
		}
		if(flag)break;
		for(ll j=0;j<=m;j++)
			(ans=ans+f[m][j]*calc(t,j)%P)%=P;
	}
	printf("%lld\n",ans);
	return 0;
}

Posted by aniesh82 on Thu, 07 Oct 2021 15:51:30 -0700