zoukankan      html  css  js  c++  java
  • [CLYZ2017]day18

    子集

    image

    solution

    60分

    枚举中位数,枚举集合大小,贪心使平均值尽量大,取最大值.

    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<stack>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #define N 2005
    using namespace std;
    double a[N],ans,sum;
    int n;
    inline void Aireen(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;++i)
    		scanf("%lf",&a[i]);
    	sort(a+1,a+1+n);
    	for(int i=2,k;i<n;++i){
    		sum=a[i];k=1;
    		for(int j=i-1,l=n;j&&l>i;--j,--l){
    			sum+=a[j]+a[l];k+=2; 
    			ans=max(ans,sum/k-a[i]);
    		}
    	}
    	for(int i=3,k;i<n;++i){
    		sum=a[i-1]+a[i];k=2;
    		for(int j=i-2,l=n;j&&l>i;--j,--l){
    			sum+=a[j]+a[l];k+=2; 
    			ans=max(ans,sum/k-(a[i-1]+a[i])/2.0);
    		}
    	}
    	printf("%.5lf\n",ans);
    }
    int main(){
    	freopen("subset.in","r",stdin);
    	freopen("subset.out","w",stdout);
    	Aireen();
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    

    100分

    \(yy\)一下发现中位数为一个数时值更大.
    枚举中位数,可以发现这是一个关于集合大小的单峰函数,三分即可.

    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<stack>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #define N 200005
    using namespace std;
    int n,l,r,m1,m2;
    double a[N],s[N],ans;
    inline double f(int x,int i){
    	return (s[n]-s[n-x]+s[i]-s[i-x-1])/(x<<1|1)-a[i];
    }
    inline void Aireen(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;++i)
    		scanf("%lf",&a[i]);
    	sort(a+1,a+1+n);
    	for(int i=1;i<=n;++i) 
    		s[i]=s[i-1]+a[i];
    	for(int i=1;i<=n;++i){
    		l=1;r=min(n-i,i-1);
    		while(l+2<r){
    			m1=l+(r-l)/3;m2=r-(r-l)/3;
    			if(f(m1,i)<f(m2,i)) l=m1;
    			else r=m2;
    		}
    		for(int j=l;j<=r;++j)
    			ans=max(ans,f(j,i));
    	}
    	printf("%.5lf\n",ans);
    }
    int main(){
    	freopen("subset.in","r",stdin);
    	freopen("subset.out","w",stdout);
    	Aireen();
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    

    子串

    image

    100分

    将字符串建成\(AC\)自动机,\(f[i]\)表示从节点\(i\)到结束的期望步数.
    \(f[i]=1+\frac{1}{26}\sum_{j='a'}^{'z'}f[tr[i][j]]\).
    如果\(i\)为结束节点,则\(f[i]=0\).
    根据关系式高斯消元即可(分母移项即为整式方程).

    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<stack>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #define K 26
    #define M 15
    #define N 155
    #define P 1000000007
    using namespace std;
    typedef long long ll;
    int a[N][N],tr[N][K],nxt[N],f[N],n,t,cnt;
    char c[M];
    queue<int> q;
    inline void insert(){
    	int u=0,l=strlen(c+1);
    	for(int i=1;i<=l;++i){
    		c[i]-='a';
    		if(!tr[u][c[i]])
    			tr[u][c[i]]=++cnt;
    		u=tr[u][c[i]];
    	}
    	f[u]=1; 
    }
    inline void bfs(int u){
    	for(int i=0;i<K;++i)
    		if(tr[u][i]){
    			nxt[tr[u][i]]=0;
    			q.push(tr[u][i]);
    		}
    	while(!q.empty()){
    		u=q.front();q.pop();
    		for(int i=0,j;i<K;++i)
    			if(tr[u][i]){
    				q.push(tr[u][i]);j=nxt[u];
    				while(j&&!tr[j][i]) j=nxt[j];
    				nxt[tr[u][i]]=tr[j][i];
    			}
    			else{
    				j=nxt[u];
    				while(j&&!tr[j][i]) j=nxt[j];
    				tr[u][i]=tr[j][i];
    			}
    	}
    }
    inline int rev(int x){
    	int ret=1,k=P-2;
    	while(k){
    		if(k&1) ret=1ll*ret*x%P;
    		x=1ll*x*x%P;k>>=1;
    	}
    	return ret;
    }
    inline int gauss(int n){
    	int tmp;
    	for(int i=0;i<=n;++i){
    		if(!a[i][i]) 
    			for(int j=i+1;j<=n;++j)
    				if(a[j][i]){
    					for(int k=i;k<=n+1;++k)
    						swap(a[i][k],a[j][k]);
    					break;
    				}
    		for(int j=0;j<=n;++j)
    			if(j!=i&&a[j][i]){
    				tmp=1ll*a[j][i]*rev(a[i][i])%P;
    				for(int k=i;k<=n+1;++k)
    					a[j][k]=(a[j][k]-1ll*tmp*a[i][k]%P)%P;
    			}
    	}
    	for(int i=0;i<=n;++i)
    		f[i]=1ll*a[i][n+1]*rev(a[i][i])%P;
    	if(f[0]<0) f[0]+=P;
    	return f[0];
    }
    inline void Aireen(){
    	scanf("%d",&t);
    	while(t--){
    		scanf("%d",&n); 
    		cnt=0;
    		memset(f,0,sizeof(f));
    		memset(tr,0,sizeof(tr));
    		for(int i=1;i<=n;++i){
    			scanf("%s",c+1);insert();
    		}
    		bfs(0);
    		memset(a,0,sizeof(a));
    		for(int i=0;i<=cnt;++i)
    			if(f[i]){
    				a[i][i]=1;a[i][cnt+1]=0;
    			}
    			else{
    				a[i][i]=a[i][cnt+1]=26;
    				for(int j=0;j<K;++j)
    					--a[i][tr[i][j]];
    			}
    		printf("%d\n",gauss(cnt));
    	}
    }
    int main(){
    	freopen("substring.in","r",stdin);
    	freopen("substring.out","w",stdout);
    	Aireen();
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    html添加遮罩层
    html绝对定位如何居中
    springboot上传文件到本地服务器
    遍历一个文件目录,把所有的子目录都列出来
    Java判断cookie中是否有某个具体的cookie
    Redis 如何打开rdb 文件
    crontab -e 如何保存退出
    linux服务器设备上没有空间
    IDEA的SonarLint插件报错Unable to create symbol table for
    使用Rome读取RSS报错,org.xml.sax.SAXParseException: 前言中不允许有内容。
  • 原文地址:https://www.cnblogs.com/AireenYe/p/15612565.html
Copyright © 2011-2022 走看看