zoukankan      html  css  js  c++  java
  • 校内团队训练赛

    校内团队训练赛

    总结:菜。

    A - Play the Dice

    传送门

    题意:掷骰子,给长度为n的数组指点数,每个被掷中概率为1/n,m个特殊骰子,掷中还能掷一次,求期望。

    题解:水题,算出不能多掷的期望,与多掷一次的概率,联立方程直接算出ans既可。

    #include<iostream>
    using namespace std;
    
    int n,m,lin,ok[1007],ok2;
    double a[1007],ans,c,c2;
    
    int main(){
    	while(~scanf("%d",&n)){
    		ok2=0;
    		c=0;
    		c2=0;
    		for(int i=1;i<=n;i++){
    			ok[i]=0;
    			scanf("%lf",&a[i]);
    			if(a[i]>0){
    				ok2=1;
    			}
    		}
    		scanf("%d",&m);
    		for(int i=1;i<=m;i++){
    			scanf("%d",&lin);
    			ok[lin]=1;
    		}
    		if(n==m){
    			if(ok2==1){
    				printf("inf
    ");
    				continue;
    			}
    			else{
    				printf("0.00
    ");
    				continue;
    			}
    		}
    		for(int i=1;i<=n;i++){
    			if(ok[i]==1){
    				c2+=((double)1/(double)n);
    			}
    			c+=((double)1/(double)n*a[i]);
    		}
    		printf("%.2f
    ",c/(1.0-c2));
    	}
    	
    }
    

    G - Sum of Digits

    传送门

    题意:猜数,告诉你每位数之和与每位数平方之和求最小符合要求的数,答案位数大于100或找不到直接输出NO;

    题解:答案大于100直接gg,这个好,那这个数最大就900,平方最大就8100(100个9)。直接想到dp预处理,dp[ i ] [ j ] 意思是当和为 i 时,平方和为 j 时最少需要几位,dp[ i ] [ j ] = max( dp[ i ] [ j ] , dp[ i - p ] [ j - p * p ] + 1 ),其中 p 为 1 到 9 。再用 pre 数组记录最优情况由谁转移既可。

    #include<iostream>
    #include<vector>
    #include<algorithm>
    using namespace std;
    
    int dp[1007][10007],maxn=1000000007,s1,s2,t;
    
    int pre[1007][10007];
    vector<int>ho;
    int main(){
    	for(int i=0;i<=1000;i++){
    		for(int j=0;j<=10000;j++){
    			dp[i][j]=maxn;
    		}
    	}
    	dp[0][0]=0;
    	for(int i=1;i<=1000;i++){
    		for(int j=1;j<=10000;j++){
    			for(int p=1;p<=9;p++){
    				if(i>=p&&j>=p*p){
    					if(dp[i][j]>dp[i-p][j-p*p]+1){
    						pre[i][j]=p;
    						dp[i][j]=dp[i-p][j-p*p]+1;
    					}
    				}
    				else{
    					break;
    				}
    			}
    		}
    	}
    	scanf("%d",&t);
    	while(t--){
    		ho.clear();
    		scanf("%d%d",&s1,&s2);
    		if(s1>=1000||s2>=10000){
    			printf("No solution
    ");
    			continue;
    		}
    		if(dp[s1][s2]>=maxn){
    			printf("No solution
    ");
    		}
    		else{
    			int l,r,lin,sum=dp[s1][s2];
    			if(sum>100){
    				printf("No solution
    ");
    				continue;
    			}
    			l=s1,r=s2;
    			while(sum--){
    				lin=pre[l][r];
    				ho.push_back(pre[l][r]);
    				l=l-lin;
    				r=r-lin*lin;
    			}
    			sort(ho.begin(),ho.end());
    			for(int i=0;i<ho.size();i++){
    				printf("%d",ho[i]);
    			}
    			printf("
    ");
    		}
    	}
    }
    

    H - Billionaires

    传送门

    题意:n个人,名字,最开始在某个地方,有多少钱,统计 m 天,人有 t 次换城市操作,t行,告诉你第几天走,谁走了,去了哪(人移动后会把他的钱带走),输出每个城市的名字与其的钱大于其他城市的天数,天数为0的不输出(城市的钱等于该城市人的钱的和)。

    题解:单点修改线段树水题,或用map模拟。

    #include<iostream>
    #include<algorithm>
    #include<map>
    #include<stack>
    using namespace std;
    #define ll long long
    struct homura{
    	int l;
    	int r;
    	int pos;
    	ll max1;
    	ll max2;
    }ma[200007];
    stack<pair<string,int> >sa;
    struct madoka{
    	int day;
    	int p;
    	int d;
    }ex[50007];
    bool cmp(madoka a1,madoka a2){
    	return a1.day<a2.day;
    }
    map<string,int>di,nm;
    
    string s1,s2;
    int n,m,t,cntp,cntd,pw[10007],ans[200007];
    ll qian[10007],a[200007],lin;
    
    void build(int l,int r,int k){
    	ma[k].l=l;
    	ma[k].r=r;
    	//printf("%d %d
    ",l,r);
    	if(l==r){
    		ma[k].max1=a[l];
    		ma[k].max2=0;
    		ma[k].pos=l;
    		return;
    	}
    	int mid=(l+r)/2;
    	build(l,mid,k*2);
    	build(mid+1,r,k*2+1);
    	if(ma[k*2+1].max1>ma[k*2].max1){
    		ma[k].max1=ma[k*2+1].max1;
    		ma[k].pos=ma[k*2+1].pos;
    	}
    	else{
    		ma[k].max1=ma[k*2].max1;
    		ma[k].pos=ma[k*2].pos;
    	}
    	ll minn=min(ma[k*2+1].max1,ma[k*2].max1);
    	ll maxn=max(ma[k*2].max2,ma[k*2+1].max2);
    	ma[k].max2=max(minn,maxn);
    }
    
    void getall(int k){
    	if(ma[k].l==ma[k].r){
    		printf("%lld ",ma[k].max1);
    		return;
    	}
    	getall(k*2);
    	getall(k*2+1);
    }
    
    void change(int k,int p,ll money){
    	if(ma[k].l==ma[k].r){
    		ma[k].max1+=money;
    		return;
    	}
    	int mid=(ma[k].l+ma[k].r)/2;
    	if(p<=mid){
    		change(k*2,p,money);
    	}
    	else{
    		change(k*2+1,p,money);
    	}
    	if(ma[k*2+1].max1>ma[k*2].max1){
    		ma[k].max1=ma[k*2+1].max1;
    		ma[k].pos=ma[k*2+1].pos;
    	}
    	else{
    		ma[k].max1=ma[k*2].max1;
    		ma[k].pos=ma[k*2].pos;
    	}
    	ll minn=min(ma[k*2+1].max1,ma[k*2].max1);
    	ll maxn=max(ma[k*2].max2,ma[k*2+1].max2);
    	ma[k].max2=max(minn,maxn);
    }
    
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++){
    		cin>>s1>>s2>>lin;
    		nm[s1]=++cntp;
    		qian[cntp]=lin;
    		if(di[s2]==0){
    			di[s2]=++cntd;
    		}
    		a[di[s2]]+=lin;
    		pw[cntp]=di[s2];
    	}
    	scanf("%d%d",&m,&t);
    	for(int i=1;i<=t;i++){
    		cin>>lin>>s1>>s2;
    		ex[i].day=lin;
    		ex[i].p=nm[s1];
    		if(di[s2]==0){
    			di[s2]=++cntd;
    		}
    		ex[i].d=di[s2];
    	}
    	sort(ex+1,ex+1+t,cmp);
    	build(1,cntd,1);
    	int head=1;
    	for(int i=1;i<=m;i++){
    		if(ma[1].max1!=ma[1].max2){
    			ans[ma[1].pos]++;
    		}
    		for(int j=head;j<=t;j++){
    			head=j;
    			if(ex[j].day==i){
    				ll money=qian[ex[j].p];
    				int p1=pw[ex[j].p],p2=ex[j].d;
    				change(1,p1,-money);
    				change(1,p2,money);
    				pw[ex[j].p]=ex[j].d;
    				
    			}
    			else{
    				break;
    			} 
    		}
    	}
    	map<string,int >::reverse_iterator   iter;
        for(iter = di.rbegin(); iter != di.rend(); iter++){
        	//cout<<iter->first<<" "<<iter->second<<endl;
        	if(ans[iter->second]!=0){
        		sa.push({iter->first,ans[iter->second]});
    		}
        }
    	while(!sa.empty()){
    		cout<<sa.top().first;
    		printf(" %d
    ",sa.top().second);
    		sa.pop();
    	}
    } 
    

    F - Shortest Subchain

    传送门

    题意:n表示数组长度,a[i-1]有到a[i]的有向边,求a[1]到a[n]的最短走法,所选取的边顺序要递增(经过靠后的边就不能再走前面的边,a[1]到a[2]为第一条边,a[n-1]到a[n]为第n-1条边)。

    题解:dp[a[i]]=min(dp[a[i]],dp[a[i-1]]+1),然后存储最优的路径,这里我用pos数组存a[i]的最优情况的位置,然后用pre数组存该位置由哪个更优位置转移。

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<stack>
    using namespace std;
    const int maxn=1000000007;
    int n,a[100007],dp[10007],pre[100007],pos[100007];
    stack<int>sa;
    
    void init(){
    	for(int i=0;i<=n;i++)pre[i]=0,pos[i]=0;
    	for(int i=0;i<10007;i++)dp[i]=maxn;
    }
    
    int main(){
    	while(~scanf("%d",&n)){
    		init();
    		for(int i=1;i<=n;i++){
    			scanf("%d",&a[i]);
    		}
    		dp[a[1]]=0;
    		pos[a[1]]=1;
    		for(int i=2;i<=n;i++){
    			if(dp[a[i]]>dp[a[i-1]]+1){
    				dp[a[i]]=dp[a[i-1]]+1;
    				pre[i]=pos[a[i-1]];
    				pos[a[i]]=i;
    			}
    		}
    		int p = pos[a[n]];
    		while(p!=0){
    			sa.push(a[p]);
    			p=pre[p];
    		}
    		printf("%d",sa.top());
    		sa.pop();
    		while(!sa.empty()){
    			printf(" %d",sa.top());
    			sa.pop();
    		}
    		puts("");
    	}
    	return 0;
    }
    
  • 相关阅读:
    C语言的指针
    C语言的编译过程和GCC编译参数
    GCC编译器的安装
    全字段多条件搜索(api接口)
    C# Replace字符替换函数
    NetCore MemoryCache使用
    vs2017 C# ActiveX浏览器插件 创建 发布 C# windows窗体控件库(.NET Framework)注意事项
    [Asp.net core 3.1] 通过一个小组件熟悉Blazor服务端组件开发
    [AspNetCore 3.0 ] Blazor 服务端组件 Render, RenderFragment ,RenderTreeBuilder, CascadingValue/CascadingParameter 等等
    [AspNetCore 3.0] 在RazorPages/MVC 中使用 Blazor (Razor组件)
  • 原文地址:https://www.cnblogs.com/whitelily/p/13200533.html
Copyright © 2011-2022 走看看