[cf1540c2] converting array problem solving

Posted by creativodev on Thu, 27 Jan 2022 12:00:48 +0100

Problem

link

Solution

When you see the problem, first think about what "convergence" is. According to the example explanation, we know that after several operations, the array reaches a state so that no operation can change it

List formula

\[a_i<=\frac{a_i+a_{i+1}-b_i}{2} \]

\[a_{i+1}>=\frac{a_i+a_{i+1}+b_i}{2} \]

It is found that the two are equivalent, so there is no case that one side has modified and the other side has not changed, and it can be transformed into

\[a_{i+1}-a_i>=b_i \]

Difference

Therefore, considering the change of the difference score group after one modification, it is found that the difference between the two numbers after modification is \ (b_i \)

Correspondingly, considering the change of the sum of the two numbers after modification, it is found that it remains unchanged, and the average value of all numbers remains unchanged

We really want to express \ (a_1 \), so the conditions of the topic may be simplified

Assuming that the array after convergence is \ (f \), then there is

\[\sum f_i=\sum a_i \]

Because there may be several numbers in the middle without operation, the left cannot be further simplified. We really want to have all the numbers in the middle operated

Therefore, if all the adjacent numbers before the imperial order \ (i \) have been operated, then their average value remains unchanged, then there are

\[f_1+f_1+b_1+f_1+b_1+b_2+ \dots= \sum a_j \]

If \ (bp_i \) is the sum of the quadratic prefixes of \ (b \) and \ (ap_i \) is the sum of the prefixes of \ (a \), there are

\[f_1=\frac{ap_i-bp_i}{i} \]

But we don't know \ (i \), think about what this formula becomes when the middle number is not modified, and find that the equal sign becomes greater than, so there is

\[\forall i,f_1 \geq \frac{ap_i-bp_i}{i} \]

At this time, we should consider whether we can narrow the scope, that is, prove \ (f_1=\min{\frac{ap_i-bp_i}{i} \)

Proof: since \ (f_1 \) must be in the set of \ (\ frac{ap_i-bp_i}{i} \), so \ (f_1 \ GEQ \ min {\ frac {ap_i-bp_i}} \), and if \ (f_1 > \ min {\ frac{ap_i-bp_i}{i} \), then \ (\ forall I, f_1 \ NEQ \ frac {ap_i-bp_i}} \), it is not consistent with the topic, so it is proved

therefore

\[\forall i,x \geq \frac{ap_i-bp_i}{i} \]

\[\forall i,ap_i \geq ix+bp_i \]

This formula is already very good. The left side is required, and the right side is the fixed value (when \ (x \) is certain), which can be \ (DP \)

Let \ (dp_{i,j} \) represent the number of schemes with the prefix and \ (j \) in consideration of the \ (I \) bit of the \ (a \) array, and the transfer equation is

\[dp_{i,j}=\sum dp_{i-1,j-val}(val \in [0,c_i],j \geq ix+bp_i) \]

Prefixes and optimizations can be used

At this time, the complexity of \ (dp \) is \ (O(nm^2) \), where \ (m \) is the \ (a \) value range, multiplied by \ (q \) queries

According to the query of examples \ (- 100000 \) and \ (100000 \), the former \ (a \) is taken casually, and the latter has no solution, which suggests that we preprocess some answers. The others (\ (x \) is too large) are either \ (0 \), (\ (x \) is too small) or \ (\ prod(c_i+1) \)

Return to formula \ (\ forall i,x \geq \frac{ap_i-bp_i}{i} \)

  • If \ (ap_i \) is taken arbitrarily, it is also satisfied when all \ (ap_i \) are taken to the maximum, so \ (max=\min \frac{cp_i-bp_i}{i} \)

  • If \ (a \) has no solution, it is not satisfied when \ (ap_i \) is all \ (0 \), so \ (min=\min \frac{-bp_i}{i} \)

To be on the safe side, it can be expanded a little

The difference between them is about \ (m \), so the complexity becomes \ (O(n^2m^2+q) \)

Code

#include<bits/stdc++.h>
#define mod 1000000007
using namespace std;
typedef long long ll;
inline int read(){
	int res=0,f=0;
	char c=getchar();
	while(c<'0' || c>'9'){
		if(c=='-')f=1;
		c=getchar();
	}
	while(c>='0' && c<='9')res=(res<<1)+(res<<3)+c-48,c=getchar();
	return f?-res:res;
}
int n,q;
int c[110],b[110],cp[110],btp[110],bp[110];
int mn=1e5,mx=1e5;
ll dp[110][10010],ans[110],sum=1;
int main(){
	n=read();
	for(int i=1;i<=n;++i)c[i]=read(),cp[i]=cp[i-1]+c[i],sum=sum*(c[i]+1)%mod;
	for(int i=1;i<n;++i)b[i]=read(),btp[i]=btp[i-1]+b[i],bp[i]=bp[i-1]+btp[i];
	for(int i=1;i<=n;++i){
		mn=min(mn,(-bp[i-1])/i);
		mx=min(mx,(cp[i]-bp[i-1]+i-1)/i);
	}
	for(int x=mn;x<=mx;++x){
		memset(dp,0,sizeof(dp));
		for(int j=0;j<=cp[n];++j)dp[0][j]=1;
		for(int i=1;i<=n;++i){
			for(int j=max(0,i*x+bp[i-1]);j<=cp[n];++j){
				if(j<=c[i])dp[i][j]=(dp[i][j-1]+dp[i-1][j])%mod;
				else dp[i][j]=(dp[i][j-1]+dp[i-1][j]-dp[i-1][j-c[i]-1]+mod)%mod;
			}
		}
		ans[x-mn]=dp[n][cp[n]];
	}
	q=read();
	while(q--){
		int x=read();
		if(x<mn)printf("%lld\n",sum);
		else if(x>mx)printf("0\n");
		else printf("%lld\n",ans[x-mn]);
	}
}