Loading

sol of [UER #11] 切割冰片

At first, I came up with this code:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
constexpr int N=1e6+5,P=998244353;
int m,n,a[N];ll f[N];
int main(){
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cin>>m>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];a[i]=min(a[i],m);
	}
	a[++n]=m;
	f[0]=1;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=a[i];j++){
			(f[j]+=f[j-1])%=P;
		}
	}
	printf("%lld\n",f[m]);
	return 0;
}

It is said that the code is supposed to get 80 points, but due to my lack of skills, it only got 60 points.

I had tried for a long time to optimize the algorithm but failed eventually. But the official solution is strange to me because it seems to be not based on the above algorithm.

Yong's blog introduced "Newton Polynomial", able to magically keep a sequence with a length of \(10^9\). But I think the polynomial doesn't matter. What matters is to separate the sequence into \(n\) parts.

After separating the sequence into n parts, maintaining some structures able to conduct the following operations in \(O(n)\) is required:

  • Turn the sequence to its prefix-summed sequence.
  • Add \(x\) to all the numbers in the sequence.
  • Get the last number of the sequence.

just store all the numbers added and times of performing the first operation when added. Then it can be solved with the "counting paths on grids" trick.

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
constexpr int N=505,P=998244353;
int inv[N];
void init(){
	inv[1]=1;for(int i=2;i<N;i++){
		inv[i]=1ll*inv[P%i]*(P-P/i)%P;
	}
}
struct Seq{
	int a[N],L,T;
	void init(int x){L=x;}
	void upd(int x){a[++T]=x;}
	int val(){
		int ret=a[T],tmp=1;
		for(int i=T-1;i>=1;i--){
			tmp=1ll*tmp*inv[T-i]%P*(T-i+L)%P;
			ret=(ret+1ll*tmp*a[i]%P)%P;
		}
		return ret;
	}
}f[N];
int m,n,a[N],b[N];
int main(){
	ios::sync_with_stdio(false);
	cin.tie(nullptr);init();
	cin>>m>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];b[i]=a[i]=min(a[i],m);
	}
	a[++n]=m;b[n]=m;b[n+1]=m+1;
	sort(b+1,b+n+2);unique(b+1,b+n+2);
	for(int i=1;b[i]<=m;i++)f[i].init(b[i]-b[i-1]-1);
	int ans=0;for(int i=1;i<=n;i++){
		ans=1;for(int j=1;b[j]<=a[i];j++){
			f[j].upd(ans);ans=f[j].val();
		}
	}
	printf("%d\n",ans);
	return 0;
}
posted @ 2023-03-18 15:42  hihihi198  阅读(40)  评论(0)    收藏  举报