zoukankan      html  css  js  c++  java
  • 省选测试39

    总结

    时间都花到 (T1) 上了,不过也拿到了该拿的分。

    A. 老洪的遍历

    分析

    暴力的做法是按照 (B) 的值排序后,去枚举起点和终点,选出一个贡献最大的子序列和一个贡献最小的子序列,答案就是两者之差。

    发现直接强制以 (1) 为起点和以 (n) 为终点一定是最优的,因为可以同一条边正反走两次把它们的贡献抵消成 (0)

    对于 (|A_i|=1) 的部分分,建出凸包后直接二分斜率找最大最小值。

    满分的做法把贡献的式子拆成了 (frac{1}{2}(frac{B_j}{A_j}B_i-B_jfrac{B_i}{A_i}))

    如果把 (B_i) 看成横坐标,(frac{B_i}{A_i})看成横坐标,那么就是一个叉积的形式。

    找到凸包之后求面积即可。

    代码

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #define rg register
    template<typename T>void read(rg T& x){
    	x=0;rg int fh=1;
    	rg char ch=getchar();
    	while(ch<'0' || ch>'9'){
    		if(ch=='-') fh=-1;
    		ch=getchar();
    	}
    	while(ch>='0' && ch<='9'){
    		x=(x<<1)+(x<<3)+(ch^48);
    		ch=getchar();
    	}
    	x*=fh;
    }
    const int maxn=1e5+5;
    const double eps=1e-12;
    struct Node{
    	double x,y;
    	Node(){}
    	Node(rg double aa,rg double bb){
    		x=aa,y=bb;
    	}
    	friend Node operator -(const Node& A,const Node& B){
    		return Node(A.x-B.x,A.y-B.y);
    	}
    	friend double operator ^(const Node& A,const Node& B){
    		return A.x*B.y-B.x*A.y;
    	}
    }p[maxn],sta[maxn];
    int n,tp,a[maxn],b[maxn];
    double getdis(rg Node aa,rg Node bb){
    	return sqrt((aa.x-bb.x)*(aa.x-bb.x)+(aa.y-bb.y)*(aa.y-bb.y));
    }
    bool cmp(rg Node aa,rg Node bb){
    	rg double nans=(aa-p[1])^(bb-p[1]);
    	if(nans>eps) return 1;
    	else if(std::fabs(nans)<=eps) return getdis(aa,p[1])<getdis(bb,p[1]);
    	else return 0;
    }
    int main(){
    	read(n);
    	for(rg int i=1;i<=n;i++) read(a[i]);
    	for(rg int i=1;i<=n;i++) b[i]=b[i-1]+a[i];
    	for(rg int i=1;i<=n;i++){
    		p[i].x=1.0*b[i],p[i].y=1.0*b[i]/a[i];
    		if(p[i].y<p[1].y || (p[i].y==p[1].y && p[i].x<p[1].x)) std::swap(p[1],p[i]);
    	}
    	sta[tp=1]=p[1];
    	std::sort(p+2,p+1+n,cmp);
    	for(rg int i=2;i<=n;i++){
    		while(tp>1 && ((p[i]-sta[tp])^(sta[tp]-sta[tp-1]))>-eps) tp--;
    		sta[++tp]=p[i];
    	}
    	sta[tp+1]=sta[1];
    	rg double nans=0;
    	for(rg int i=1;i<=tp;i++){
    		nans+=(sta[i]^sta[i+1]);
    	}
    	printf("%.5f
    ",nans/2);
    	return 0;
    }
    

    B. 老洪的神秘操作

    分析

    一个套路的做法就是转一下差分。

    问题就变成了在一个位置加上一个数,在另一个位置减去一个数,最少多少次序列都变成 (0)

    发现 (1)(6) ,(2)(5),(3)(4) 去配对一定是最优的,那么最终匹配完成后只会剩下 (3) 种。

    大力 (dp) 求出剩下的值能够凑成多少组。

    代码

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #define rg register
    template<typename T>void read(rg T& x){
    	x=0;rg int fh=1;
    	rg char ch=getchar();
    	while(ch<'0' || ch>'9'){
    		if(ch=='-') fh=-1;
    		ch=getchar();
    	}
    	while(ch>='0' && ch<='9'){
    		x=(x<<1)+(x<<3)+(ch^48);
    		ch=getchar();
    	}
    	x*=fh;
    }
    const int maxn=505;
    int n,a[maxn],cf[maxn],ans,num[maxn],f[maxn][maxn][maxn],rk[maxn],cnt;
    int dfs(rg int now1,rg int now2,rg int now3){
    	if(!now1 && !now2 && !now3) return 0;
    	if(f[now1][now2][now3]) return f[now1][now2][now3];
    	rg int nans=0;
    	for(rg int i=now1;i>=std::max(0,now1-7);i--){
    		for(rg int j=now2;j>=std::max(0,now2-7);j--){
    			for(rg int k=now3;k>=std::max(0,now3-7);k--){
    				if(i==now1 && j==now2 && k==now3) continue;
    				if(((now1-i)*rk[1]+(now2-j)*rk[2]+(now3-k)*rk[3])%7==0) nans=std::max(nans,dfs(i,j,k)+1);
    			}
    		}
    	}
    	return f[now1][now2][now3]=nans;
    }
    int main(){
    	read(n);
    	for(rg int i=1;i<=n;i++) read(a[i]);
    	for(rg int i=1;i<=n;i++) cf[i]=a[i]-a[i-1];
    	for(rg int i=1;i<=n;i++) if(cf[i]<0) cf[i]+=7;
    	for(rg int i=1;i<=n;i++) num[cf[i]]++;
    	rg int tmp=std::min(num[1],num[6]);
    	num[1]-=tmp,num[6]-=tmp;
    	ans+=tmp;
    	tmp=std::min(num[2],num[5]);
    	num[2]-=tmp,num[5]-=tmp;
    	ans+=tmp;
    	tmp=std::min(num[3],num[4]);
    	num[3]-=tmp,num[4]-=tmp;
    	ans+=tmp;
    	for(rg int i=1;i<=6;i++){
    		if(num[i]) rk[++cnt]=i;
    	}
    	printf("%d
    ",ans+num[rk[1]]+num[rk[2]]+num[rk[3]]-dfs(num[rk[1]],num[rk[2]],num[rk[3]]));
    	return 0;
    }
    

    C. 老洪的数组

    分析

    不难发现对于 (f(x,y)) ,(C_j) 对其系数的贡献是从 ((1,j)) 走到 ((x,y)) 的方案数。

    对于询问分块,当修改的数量大于等于块长对于整体更新答案,否则就暂时存一下。

    代码

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<iostream>
    #define rg register
    template<typename T>void read(rg T& x){
    	x=0;rg int fh=1;
    	rg char ch=getchar();
    	while(ch<'0' || ch>'9'){
    		if(ch=='-') fh=-1;
    		ch=getchar();
    	}
    	while(ch>='0' && ch<='9'){
    		x=(x<<1)+(x<<3)+(ch^48);
    		ch=getchar();
    	}
    	x*=fh;
    }
    const int maxn=2e5+5,mod=1e9+7;
    inline int addmod(rg int now1,rg int now2){
    	return now1+=now2,now1>=mod?now1-mod:now1;
    }
    inline int delmod(rg int now1,rg int now2){
    	return now1-=now2,now1<0?now1+mod:now1;
    }
    inline int mulmod(rg long long now1,rg int now2){
    	return now1*=now2,now1>=mod?now1%mod:now1;
    }
    struct jie{
    	int x,y;
    	jie(){}
    	jie(rg int aa,rg int bb){
    		x=aa,y=bb;
    	}
    }q[maxn];
    int f[25][maxn],a[maxn],n,m,blo,jc[maxn],jcc[maxn],ny[maxn],tot,lst;
    int getC(rg int nn,rg int mm){
    	return mulmod(jc[nn],mulmod(jcc[mm],jcc[nn-mm]));
    }
    void pre(){
    	ny[1]=1;
    	for(rg int i=2;i<=n+20;i++) ny[i]=mulmod(mod-mod/i,ny[mod%i]);
    	jc[0]=jcc[0]=1;
    	for(rg int i=1;i<=n+20;i++){
    		jc[i]=mulmod(jc[i-1],i);
    		jcc[i]=mulmod(jcc[i-1],ny[i]);
    	}
    }
    void build(){
    	for(rg int i=1;i<=n;i++) f[0][i]=a[i];
    	for(rg int i=1;i<=20;i++){
    		for(rg int j=1;j<=n;j++){
    			f[i][j]=addmod(f[i-1][j],f[i][j-1]);
    		}
    	}
    }
    int main(){
    	read(n),read(m);
    	for(rg int i=1;i<=n;i++) read(a[i]);
    	blo=sqrt(20*n);
    	pre(),build();
    	rg int aa,bb,cc,tmp;
    	for(rg int now=1;now<=m;now++){
    		read(aa),read(bb),read(cc);
    		if(aa==1){
    			q[++tot]=jie(bb,cc);
    			if(tot%blo==0){
    				for(rg int i=lst+1;i<=tot;i++) a[q[i].x]=q[i].y;
    				lst=tot;
    				build();
    			}
    		} else {
    			tmp=f[bb][cc];
    			for(rg int i=lst+1;i<=tot;i++){
    				if(q[i].x<=cc && q[i].x>=1) tmp=delmod(tmp,mulmod(a[q[i].x],getC(bb+cc-1-q[i].x,bb-1)));
    				std::swap(a[q[i].x],q[i].y);
    				if(q[i].x<=cc && q[i].x>=1) tmp=addmod(tmp,mulmod(a[q[i].x],getC(bb+cc-1-q[i].x,bb-1)));
    			}
    			for(rg int i=tot;i>=lst+1;i--) std::swap(a[q[i].x],q[i].y);
    			printf("%d
    ",tmp);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    前端的缓存
    微信开发小程序Taro框架
    前端必会的Nginx
    微信开发小程序
    如何进行有效的沟通
    产品经理和项目经理的区别
    Django之模板
    Django之视图
    Django之路由系统
    创建一个简单的Django项目
  • 原文地址:https://www.cnblogs.com/liuchanglc/p/14538206.html
Copyright © 2011-2022 走看看