2022.7.9 AGC044E&AGC049D

AGC049D

题意:计数 \(\{a_n\geqslant 0\}\) 使得 \(\sum a=m\)\(2a_i\leqslant a_{i-1}+a_{i+1}\)

瞎扯:貌似是之前的讲课题。首先想到查分 \(d'\),条件 \(2\) 等价于 \(d'\) 递增。有性质:只有最后 \(\sqrt m\) 个位置 \(d'\) 有值。不妨再差分一次 \(d\),就去掉了递增的条件。但是我发现,我只能做 \(a\) 递增的情况/kk

正解:考虑那个我会的情况,其实就是做完全背包。应该要敏感地发现完全背包计数是乘一个多项式,也非常好撤销。由于它一定是一些递减、一段平的、一些递增,我们不妨枚举第一个最小值的位置,对前对后都做完全背包就行,我们每次也只用乘以一个差项即可。时间复杂度还是 \(O(m\sqrt m)\)

#include<bits/stdc++.h>
using namespace std;
#define inf 1e9
const int maxn=2e5+10;
const int mod=1e9+7;
inline int read(){
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return x*f;
}
#define ll long long
int n,m,f[maxn],ans;
inline void A(ll x){for(ll i=x;i<=m;i++)f[i]=(f[i]+f[i-x])%mod;}
inline void D(ll x){for(ll i=m;i>=x;--i)f[i]=(f[i]-f[i-x])%mod;}
int main(){
	n=read(),m=read();f[0]=1;A(n);
	for(int i=2;i<=n;i++)A(1ll*(n-i+1)*(n-i+2)/2);
	for(int i=1;i<=n;i++){
		if(1ll*i*(i-1)/2<=m)ans=(ans+f[m-1ll*i*(i-1)/2])%mod;
		A(1ll*i*(i+1)/2),D(1ll*(n-i)*(n-i+1)/2);
	}printf("%d\n",(ans+mod)%mod);
    return 0;
}

AGC044E Random Pawn

题意:有一个环,初始等概率出生在一个整点,每个时刻在位置 \(p\) 可以选择停止并获得 \(a_p\),或者继续,交付 \(b_p\) 并随机移动到 \(p-1\)\(p+1\)。求期望收益。

瞎扯:需要满足 \(E_x=\max\{a_x,-b_x+\frac{E_{x-1}+E_{x+1}}2\}\),并且已知 \(a_x\) 最大时 \(E_x=a_x\)。你看这个一脸凸包的样子,然而我不会处理。

正解:我们考虑从 \(a\) 最大处断环为链。有一个 trick 就是说:

对于形如 \(f_i=\max\{a_i,\frac{f_{i-1}+f_{i+1}}{2}\}\) 的转移,我们将 \((i,a_i)\) 做一个凸包,然后把所有不在边上的点挪到边上即可。

我们考虑将方程变换为上述形式。随意变换即可。

#include<bits/stdc++.h>
using namespace std;
#define inf 1e9
const int maxn=2e5+10;
const int mod=1e9+7;
inline int read(){
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return x*f;
}
#define db double
int n,m;db a[maxn<<1],b[maxn<<1],c[maxn<<1];
int q[maxn],top;db ans;
inline db slope(int x,int y){return (a[y]-a[x])/(y-x);}
int main(){
	n=read();db Mx=-1;int p=0;
	for(int i=1;i<=n;i++)scanf("%lf",a+i),a[n+i]=a[i];
	for(int i=1;i<=n;i++)scanf("%lf",b+i),b[n+i]=b[i];
	for(int i=1;i<=n;i++)if(a[i]>Mx)Mx=a[i],p=i;q[++top]=p;
	if(n==2)return printf("%.12lf\n",(Mx+max(a[p+1],Mx-b[p+1]))/2)&0;
	for(int i=p+2;i<=n+p;i++)c[i]=2*(b[i-1]+c[i-1])-c[i-2],a[i]-=c[i];
	for(int i=p+1;i<=n+p;i++){
		while(top>1&&slope(q[top-1],q[top])<slope(q[top],i))top--;
		q[++top]=i;
	}
	for(int i=1;i<top;i++){
		db k=slope(q[i],q[i+1]);
		db b=a[q[i]]-k*q[i];
		for(int j=q[i];j<q[i+1];j++)ans+=k*j+b+c[j];
	}printf("%.12lf\n",ans/n);
	return 0;
}
posted @ 2022-07-09 10:58  syzf2222  阅读(29)  评论(0编辑  收藏  举报