zoukankan      html  css  js  c++  java
  • 【日记】12.27/【题解】CF Edu79

    12.27

    CF Edu79

    A.New Year Garland

    题意:有r,g,b个红绿蓝色气球,现问是否可以排成一列,使得没有两个相邻气球颜色相同。

    思路:如果最大值>两个小数+1,就挂了。

    #include<bits/stdc++.h>
    using namespace std;
    #define LL long long
    #define mid ((l+r)>>1)
    const int M=1e5+20;
    struct Task{
    	int a,b,c;
    	void init(){
    		scanf("%d%d%d",&a,&b,&c);
    	}
    	void run(){
    		init();
    		int mx=max(a,max(b,c)),sum=a+b+c;
    		if (mx>sum-mx+1)
    			printf("No
    ");
    		else
    			printf("Yes
    ");
    	}
    }t;
    int main(){
    	int T;
    	scanf("%d",&T);
    	for(int i=1;i<=T;++i)
    		t.run();
    	return 0;
    }
    

    B.Verse For Santa

    题意:有n个片段,每个片段需要a[i]分钟,一共有s分钟,必须从头开始按顺序念,但可以skip掉一个。问为了念出最多的片段,需要删掉哪一个?

    思路:一万个假算法。其实很简单,先不skip,找到临界点,那么要么skip第一个念不完的,要么skip掉前面最大的,选最大的那个skip就行了。

    #include<bits/stdc++.h>
    using namespace std;
    #define LL long long
    #define mid ((l+r)>>1)
    const int M=1e5+20;
    struct Task{
    	int n,s,a[M];
    	int mxp=0;
    	void init(){
    		mxp=0;
    		scanf("%d%d",&n,&s);
    		for(int i=1;i<=n;++i)
    			scanf("%d",&a[i]);
    		a[n+1]=0;
    	}
    	void run(){
    		init();
    		int p=1;
    		while(p<=n&&a[p]<=s){
    			s-=a[p];
    			if (a[p]>a[mxp])
    				mxp=p;
    			++p;
    		}
    		if (p>n||n==1)
    			printf("0
    ");
    		else{
    			if (a[mxp]>a[p])
    				printf("%d
    ",mxp);
    			else
    				printf("%d
    ",p);
    		}
    	}
    }t;
    int main(){
    	int T;
    	scanf("%d",&T);
    	for(int i=1;i<=T;++i)
    		t.run();
    	return 0;
    }
    

    C.Stack of Presents

    题意:有一堆礼物,从上到下编号依次为a1,a2,……an。现在要顺次拿b1,b2,……,bn的礼物,每次拿都需要消耗2k+1秒,k是目标礼物上面的礼物个数。但每次拿一个礼物之后,可以把上面的礼物按任意顺序排序。现在问按顺序拿出所有礼物的最小时间是多少。

    思路:可以想到,如果当前礼物在之前已经被搬动过,那么拿这个礼物的时间就是1,因为上次搬动它的时候,你一定能有办法把它安排到拿它的时候恰好在最顶上。所以直接设置指针和vis数组,如果没被访问过就往后找,找的过程中把翻过的全都在vis里面记录一下即可。

    #include<bits/stdc++.h>
    using namespace std;
    #define LL long long
    #define mid ((l+r)>>1)
    #define db(x) cout<<#x<<":"<<x<<endl;
    const int M=1e5+20;
    struct Task{
    	int n,m,a[M],b[M],vis[M];
    	void init(){
    		scanf("%d%d",&n,&m);
    		for(int i=1;i<=n;++i)
    			scanf("%d",&a[i]),vis[i]=0;
    		for(int i=1;i<=m;++i)
    			scanf("%d",&b[i]);
    	}
    	void run(){
    		init();
    		LL ans=0;
    		int p=1;
    		for(int i=1;i<=m;++i){
    			if (vis[b[i]])
    				++ans;
    			else{
    				while(p<=n&&a[p]!=b[i])
    					vis[a[p]]=1,++p;
    				ans+=2*(p-i)+1;
    			}
    		}
    		printf("%lld
    ",ans);
    	}
    }t;
    int main(){
    	int T;
    	scanf("%d",&T);
    	for(int i=1;i<=T;++i)
    		t.run();
    	return 0;
    }
    

    D.Santa's Bot

    题意:有n个孩子,每个孩子都有k个想要的礼物,每个礼物都有不同编号。现在有个算法,首先随机选一个孩子,之后从这个孩子的愿望清单里面随机选一个礼物,之后再随机选一个孩子,把刚刚那个礼物送给这个孩子。问有多少可能性,使得能送对。

    思路:首先统计所有礼物被选中的概率,显然是读入的时候碰到一次就+(frac{1}{n}*frac{1}{k})。之后由于最后一次也是随机选要送的人,所以把每种礼物的被选中的概率*想要它的孩子个数/n即可。

    #include<bits/stdc++.h>
    using namespace std;
    #define LL long long
    #define mid ((l+r)>>1)
    const int M=1e6+20,P=998244353;
    int Inv[M];
    void ln_Inv(int p){  
        Inv[0]=Inv[1]=1;
        for(int i=2;i<=1e6;i++)
            Inv[i]=1LL*(p-p/i)*Inv[p%i]%p; 
    }  
    struct Task{
    	int n,giftnum[M],giftprob[M];
    	void run(){
    		scanf("%d",&n);
    		for(int i=1;i<=n;++i){
    			int k;
    			scanf("%d",&k);
    			int prob=1LL*Inv[n]*Inv[k]%P;
    			for(int j=1;j<=k;++j){
    				int c;
    				scanf("%d",&c);
    				++giftnum[c];
    				giftprob[c]=(giftprob[c]+prob)%P;
    			}
    		}
    		int ans=0;
    		for(int i=1;i<=1e6;++i)
    			ans=(ans+1LL*giftprob[i]*giftnum[i]%P*Inv[n]%P)%P;
    		printf("%d
    ",ans);
    	}
    }t;
    int main(){
    	ln_Inv(P);
    	t.run();
    	return 0;
    }
    
  • 相关阅读:
    1703技术笔录
    技术开发感想
    1701技术随笔
    12月份技术随笔
    光照效果函数
    冰冻效果
    反色效果函数
    哈哈镜效果
    黑白效果函数
    羽化效果
  • 原文地址:https://www.cnblogs.com/diorvh/p/12110224.html
Copyright © 2011-2022 走看看