zoukankan      html  css  js  c++  java
  • [noip模拟赛2017.7.10]

    全国信息学分区联赛模拟试题(一)

    【试题概览】

    题目名称 漂亮字串 Se Prison
    提交文件 bs.* set.* prison.*
    输入文件 bs.in set.in prison.in
    输出文件 bs.ans set.ans prison.ans
    时间限制 1s 1s 1s
    空间限制 128MB 128MB 128MB
    题目来源 Codejam codejam cadejam

    1. 漂亮字串

    【题目描述】

    Caima 认为 O 和 X 是最优美的两个字母,由 O、X 组成的串是最优美的串。在这些最优美的串中, 如果任意只包含 X 的子串,长度不超过 maxX,任意只包含 O 的子串,长度不超过 maxO,且整个串 最多有 countO 个 O,countX 个 X。那么这个就是超级优美无敌串。
    现在 Caima 想知道最长的超级优美无敌串有多长,希望你告诉他。

    【输入格式】

    输入包含多行,至文件结束为止;
    每行四个数,依次是 countO、countX、maxO、maxX。

    【输出格式】

    每组数据输出一行,一个数表示最长的超级优美无敌串的长度。

    【数据规模】

    0<=countO,countX,maxO,maxX<=1000000

    【输入样例】

    10 10 0 0
    3 5 1 1

    【输出样例】

    0
    7

    【注意事项】

    第二个样例的解释:”XOXOXOX”
    最多 1000 组数据,其中 30%的数据 0<=countO,countX,maxO,maxX<=20,且数据组数不超过 20 组。

    题解

    首先第一题是一道比较傻的题目,不该花长时间,考虑问题还是不能一针见血。然后就是没有开long long。就是普通的摸拟把。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <cstdlib>
    using namespace std;
    int co,cx,mo,mx,flag;
    void Pre_Check(){
    	if(cx==0||mx==0){
    		printf("%d
    ",min(co,mo));
    		flag=1;
    		return;
    	}
    	if(mo==0||co==0){
    		printf("%d
    ",min(cx,mx));
    		flag=1;
    		return;
    	}
    	if(cx==co){
    		printf("%d
    ",co+cx);
    		flag==1;
    		return;
    	}
    }
    int main()
    {
    	freopen("bs.in","r",stdin);
    	freopen("bs.out","w",stdout);
    	while(~scanf("%d%d%d%d",&co,&cx,&mo,&mx))
    	{
    		flag=0;
    		Pre_Check();
    		if(flag==1)continue;
    		if(co>cx){
    			int div=cx+1;
    			long long Re_Num=div*mo;
    			if(Re_Num>co)Re_Num=co;
    			printf("%lld
    ",Re_Num+cx);
    			continue;
    		}
    		if(cx>co){
    			int div=co+1;
    			long long Re_Num=div*mx;
    			if(Re_Num>cx)Re_Num=cx;
    			printf("%lld
    ",Re_Num+co);
    			continue;
    		}
    	}
    	return 0;
    } 
    

    2. Set

    【题目描述】

    现在给你一些连续的整数,它们是从 A 到 B 的整数。一开始每个整数都属于各自的集合,然后你 需要进行如下操作:
    每次选择两个属于不同集合的整数,如果这两个整数拥有大于等于 P 的公共质因数,那么把它们 所在的集合合并。
    反复上述操作,直到没有可以合并的集合为止。
    现在 Caima 想知道,最后有多少个集合。

    【输入格式】

    一行,三个整数 A,B,P。

    【输出格式】

    一个树,表示最终集合的个数。

    【数据规模】

    A<=B<=100000;2<=P<=B。

    【输入样例】

    10 20 3

    【输出样例】

    7

    【注意事项】

    有 80%的数据 B<=1000.
    样例解释{10,20,12,15,18},{13},{14},{16},{17},{19}。

    题解

    第二题 其实是一道比较好想的题,这几天都在强调一种思想,如果我不好控制任意两个数的关系,不如用已知条件筛选,将质数表做出来然后,它能求得哪些目标数。然后就是用并查集合并了,复杂度比较低的。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <cstdlib>
    
    using namespace std;
    
    int flag[100010],prime[100010],l,r,p,fa[100010];
    
    int Findf(int x){
    	if(fa[x]==x)return x;
    	else return Findf(fa[x]);
    }
    
    void Mergef(int x,int y){
    	int fx=Findf(x);
    	int fy=Findf(y);
    	fa[fy]=fx;
    }
    
    void Prime_Make(){
    	for(int i=2;i<=100000;i++){
    		if(!flag[i])flag[i]=1,prime[++prime[0]]=i;
    		for(int j=1;j<=prime[0]&&i*prime[j]<=100000;j++){
    			flag[i*prime[j]]=1;
    			if(i%prime[j]==0)break;
    		}
    	}
    }
    
    void Find_Diffe(){
    	for(int i=l;i<=r;i++)fa[i]=i;
    	for(int i=1;i<=prime[0];i++){
    		if(prime[i]<p)continue;
    		if(prime[i]>r)break;
    		int st;
    		if(l%prime[i]==0)st=l;
    		else st=(l/prime[i]+1)*prime[i];
    		int last=st;
    		st+=prime[i];
    		for(int j=st;j<=r;j+=prime[i])
    			Mergef(last,j);
    	}
    }
    
    void Ans_Output(){
    	int ans=0;
    	for(int i=l;i<=r;i++)if(fa[i]==i)ans++;
    	printf("%d",ans);
    }
    
    int main()
    {
    	freopen("set.in","r",stdin);
    	freopen("set.out","w",stdout);
    	scanf("%d%d%d",&l,&r,&p);
    	Prime_Make();
    	Find_Diffe();
    	Ans_Output();
    	return 0;
    } 
    

    3. Prison

    【题目描述】

    Caima 王国中有一个奇怪的监狱,这个监狱一共有 P 个牢房,这些牢房一字排开,第 i 个仅挨着第 i+1 个(最后一个除外)。现在正好牢房是满的。
    上级下发了一个释放名单,要求每天释放名单上的一个人。这可把看守们吓得不轻,因为看守们 知道,现在牢房中的 P 个人,可以相互之间传话。如果某个人离开了,那么原来和这个人能说上话的 人,都会很气愤,导致他们那天会一直大吼大叫,搞得看守很头疼。如果给这些要发火的人吃上肉, 他们就会安静点。 现在看守们想知道,如何安排释放的顺序,才能使得他们花费的肉钱最少。

    【输入格式】

    第一行 2 个数 P 和 Q,Q 表示释放名单上的人数;
    第二行 Q 个数,表示要释放哪些人。

    【输出格式】

    仅一行,表示最少要给多少人次送肉吃。

    【数据规模】

    1<=P<=1000
    1<=Q<=100

    【输入样例】

    20 3
    3 6 14

    【输出样例】

    35

    【注意事项】

    Q<=P;且 50%的数据 1<=P<=100;1<=Q<=5。

    题解

    第三题 哎。看到题后,想都没想就打暴力,结果又是数组开小了,爆了零(QAQ)。哎其实正解也好想,记忆化搜索or dp均可。第l个应被释放的犯人,到第r个应该被释放的犯人之间的最优解,然后分治;

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <cstdlib>
    using namespace std;
    int p,release,a[1100],flag[110][110],dp[110][110],check[1010],rls[110];
    int dfs(int l,int r){
    	if(flag[l][r])return dp[l][r];
    	flag[l][r]=1;
    	if(l+1==r)return dp[l][r]=0;
    	dp[l][r]=2147483647;
    	for(int pos=l+1;pos<r;pos++)
    		dp[l][r]=min(dfs(l,pos)+dfs(pos+1,r),dp[l][r]);
    	dp[l][r]+=a[r]-a[l]-2;
    	return dp[l][r];
    }
    int main()
    {
    	freopen("prison.in","r",stdin);
    	freopen("prison.out","w",stdout);
    	scanf("%d%d",&p,&release);
    	for(int i=1;i<=release;i++)scanf("%d",&a[i]);
    	a[0]=0,a[release+1]=p+1;
    	dfs(0,release+1);
    	printf("%d",dp[0][release+1]);
    	return 0;
    } 
    
  • 相关阅读:
    easyui
    H+ Se7en WebUI
    WEB IM
    PowerDesigner 导出 Excel
    SSO跨域 CodeProject
    ICU 是一种说不出的痛啊
    C#的Main(String[] args)参数输入问题
    C# TabControl标签的隐藏
    在foreach的判断条件里执行方法会有效率问题吗?
    C#编程命名规范推荐
  • 原文地址:https://www.cnblogs.com/DexterYsw/p/7191460.html
Copyright © 2011-2022 走看看