「NOI十联测」奥义商店

「NOI十联测」奥义商店

若lzz想花费最少的钱,那么显然要选择数目较少的颜色。

先考虑暴力的写法。

每次向两边统计,每个物品要求被买的概率可以由上一个物品推出。

now=1;//now 被买概率 M 选择的颜色的数目
for(int q=1;st+d*q<=n&&q<=cnt[1];++q){
    now*=(M-q+1.0)/(n-1-q+1);//当前点被涂上选择的颜色的概率 * 先前的物品也涂上选择的颜色
    ans+=val[st+d*q]*now;
}
now=1;
for(int q=1;st-d*q>0&&q<=cnt[1];++q){//同上
    now*=(M-q+1.0)/(n-1-q+1);
    ans+=val[st-d*q]*now;
}

观察到,当(2 leq t),那么(M leq {n over 2}),而此时now的衰减极快,大约可以在(log_2(10^8))次数内不再对答案的有贡献(精度问题)。因此可以做到查询复杂度(o(log)),修改复杂度(o(1))

(t=1),颜色只有一种,故只要是在等差序列上的点,都要被选中。

​ 对于(sqrt n leq d)的情况,可以暴力计算,询问复杂度(o(sqrt n)),修改复杂度(o(1 ))

​ 对于(sqrt n geq d)的情况,可以对每个d和每个起始点都预处理一遍答案,询问复杂度(o(1)),修改复杂度(o(sqrt n ))

故可以得到时间和空间都为(o(n sqrt n))的算法。

#include<bits/stdc++.h>
#define rep(q,a,b) for(int q=a,q##_end_=b;q<=q##_end_;++q)
#define dep(q,a,b) for(int q=a,q##_end_=b;q>=q##_end_;--q)
#define mem(a,b) memset(a,b,sizeof a )
#define debug(a) cerr<<#a<<' '<<a<<"___"<<endl
using namespace std;
void in(int &r) {
	static char c;
	r=0;
	while(c=getchar(),c<48);
	do r=(r<<1)+(r<<3)+(c^48);
	while(c=getchar(),c>47);
}
bool cur1;
const int mn=100005;
int n,m,val[mn];
int sq,sum[330][330];
void get1(int st,int d){
	if(d<=sq)printf("%.4lf
",(double)sum[d][st%d]);
	else{
	    int ans=val[st];
		for(int q=1;st+d*q<=n;++q)ans+=val[st+d*q];
		for(int q=1;st-d*q>0;++q)ans+=val[st-d*q];
		printf("%.4lf
",(double)ans);
	}
}
void get(int col,int st,int d,int M){
	double ans=val[st],now=1;
	for(int q=1;st+d*q<=n&&q<=M;++q){
	   	if(now<1e-10)break;
	    now*=(M-q+1.0)/(n-1-q+1);
	    ans+=val[st+d*q]*now;
	}
	now=1;
	for(int q=1;st-d*q>0&&q<=M;++q){
		if(now<1e-10)break;
	    now*=(M-q+1.0)/(n-1-q+1);
	    ans+=val[st-d*q]*now;
	}
	printf("%.4lf
",ans);
}
void change(int x,int v){
    int d=v-val[x];
	val[x]=v;
	rep(w,1,sq)sum[w][x%w]+=d;
}
bool cur2;
int main(){
//	cerr<<(&cur1-&cur2)/1024.0/1024.0;
	freopen("lzz.in","r",stdin);
	freopen("lzz.out","w",stdout);
    in(n),in(m);
    rep(q,1,n)in(val[q]);
		sq=sqrt(n)+1;
	    rep(q,1,sq)rep(w,1,n)sum[q][w%q]+=val[w];
        int a,b,c,d;
	    while(m--){
		    in(a),in(b),in(c);
		    if(a==1)change(b,c);
		    else{
			    in(d);
			    int M=1e9;
			    rep(q,1,b)in(a),M=min(a,M);
			    if(b==1)get1(c,d);
				else get(b,c,d,M);
		}
	}
    return 0;
}
原文地址:https://www.cnblogs.com/klauralee/p/11283544.html