• noip模拟测试6


    A. 辣鸡

    内存限制:64 MiB 时间限制:1000 ms 标准输入输出
    题目类型:传统 评测方式:文本比较
     

    题目描述

    辣鸡ljh NOI之后就退役了,然后就滚去学文化课了。

    然而在上化学课的时候,数学和化学都不好的ljh却被一道简单题难住了,受到了大佬的嘲笑。

    题目描述是这样的:

    在一个二维平面上有一层水分子,请问形成了多少个氢键?

    这个二维平面可以看做一个类似棋盘的东西,每个格子可以容纳一个水分子,左下角的格子为(0,0),这个格子右边的格子为(1,0),上方格子为(0,1),以此类推。

    辣鸡ljh当然不会做了,所以他来求助JeremyGou,JeremyGou一眼就看穿了真相,并想用这道题来考一考正在做NOIP模拟赛的你。

    注:在本题中,我们认为一个水分子能与和它曼哈顿距离为2且直线距离小于2的其他格子形成氢键。

    输入格式

    一个整数n

    接下来n行,每行给出四个整数x1,y1,x2,y2

    表示以(x1,y1)为左下角,(x2,y2)为右上角的矩形中每个格子都有一个水分子。

    给出的所有矩形没有交集。

    输出格式

    一个整数,表示氢键的数量。

    样例

    样例输入1

    3
    0 0 0 0
    0 1 1 2
    2 2 2 3
    

    样例输出1

    5
    

    样例1解释

    左图为水分子的排布,右图中的绿色线条表示氢键。
    image

    样例输入2

    10
    1 8 8 9
    0 3 10 7
    0 0 7 0
    0 2 9 2
    4 10 8 10
    10 0 10 2
    0 10 0 10
    8 0 9 1
    0 8 0 9
    9 8 10 8
    

    样例输出2

    157
    

    数据范围与提示


     析:刚开始看到这道题,不知道什么是曼哈顿距离,解释一下:在平面上,坐标(x1,y1)的i点与坐标(x2,y2)的j点的曼哈顿距离为:d(i,j)=|X1-X2|+|Y1-Y2|.

      所以,我们要求的就是四个方向上可以连成的氢键;

      在考场上,我看到一个N=1的测试点,找到了规律:一个矩形内部的氢键个数为 (x2-x1)*(y2-y1)*2,5分到手。。。。。。。

      当时我还打了个暴力dfs,应该是边界条件问题打假了;

      正解为大模拟,将答案分为四部分:1.每个矩形内部的氢键。2.矩形左右相邻的氢键。3.矩形上下相邻的氢键。4.矩形对角线相邻的氢键,利用sort排序后模拟即可

      上代码:

    #include<bits/stdc++.h>
    #define re register int
    #define ll long long
    #define int long long
    using namespace std;
    const int N=1e9+5;
    int n,cnt,sum,ans;
    map<pair<int,int>,bool> p;
    struct CUN
    {
    	int x1,y1,x2,y2;
    }use[2000010];
    int my(CUN a,CUN b)
    {
    	if(a.x1==b.x1)
    		return a.y1<b.y1;
    	return a.x1<b.x1;
    }
    #undef int
    int main()
    {
    	#define int long long
    	scanf("%lld",&n);
    	int x1,y1,x2,y2;
    	for(re i=1;i<=n;i++)
    	{
    		scanf("%lld%lld%lld%lld",&x1,&y1,&x2,&y2);
    		ans+=((x2-x1)*(y2-y1))<<1;
    		use[i].x1=x1;
    		use[i].y1=y1;
    		use[i].x2=x2;
    		use[i].y2=y2;
    	}
    	sort(use+1,use+n+1,my);
    	for(re i=1;i<n;i++)
    	{
    		for(re j=i+1;j<=n;j++)
    		{
    			if(use[j].x1-use[i].x2>1)
    				break;
    			if(use[j].y2<use[i].y1-1||use[j].y1>use[i].y2+1)
    				continue;
    			if(use[j].x1<=use[i].x2)  //上下相邻
    			{
    				if(use[i].x1==use[j].x1)
    				{
    					if(use[i].x2==use[j].x2)
    						ans+=use[i].x2-use[i].x1;
    					else if(use[j].x2>use[i].x2)
    						ans+=((use[i].x2-use[i].x1)<<1)+1;
    					else if(use[i].x2>use[j].x2)
    						ans+=((use[j].x2-use[j].x1)<<1)+1;
    				}
    				else if(use[i].x2==use[j].x2)
    				{
    					if(use[i].x1==use[j].x1)
    						ans+=use[i].x2-use[i].x1;
    					else if(use[i].x1>use[j].x1)
    						ans+=((use[i].x2-use[i].x1)<<1)+1;
    					else if(use[j].x1>use[i].x1)
    						ans+=((use[j].x2-use[j].x1)<<1)+1;
    				}
    				else if(use[i].x2>use[j].x2)
    					ans+=(use[j].x2-use[j].x1+1)<<1;
    				else
    					ans+=(use[i].x2-use[j].x1+1)<<1;
    					
    			}
    			else //左右
    			{
    				if(abs(use[j].y1-use[i].y2)==1)//对角线
    					++ans;
    				else if(use[i].y1==use[j].y1)
    				{
    					if(use[i].y2==use[j].y2)
    						ans+=use[i].y2-use[i].y1;
    					else if(use[j].y2>use[i].y2)
    						ans+=((use[i].y2-use[i].y1)<<1)+1;
    					else if(use[i].y2>use[j].y2)
    						ans+=((use[j].y2-use[j].y1)<<1)+1;
    				}
    				else if(use[i].y2==use[j].y2)
    				{
    					if(use[i].y1==use[j].y1)
    						ans+=use[i].y2-use[i].y1;
    					else if(use[i].y1>use[j].y1)
    						ans+=((use[i].y2-use[i].y1)<<1)+1;
    					else if(use[j].y1>use[i].y1)
    						ans+=((use[j].y2-use[j].y1)<<1)+1;
    				}
    				else if(use[i].y2>use[j].y2)
    					ans+=(use[j].y2-use[j].y1+1)<<1;
    				else
    					ans+=(use[i].y2-use[j].y1+1)<<1;
    			}
    		}
    	}
    	printf("%lld\n",ans);
    	return 0;
    }
    

    B. 模板

    内存限制:512 MiB 时间限制:1000 ms 标准输入输出
    题目类型:传统 评测方式:文本比较
     

    题目描述

    辣鸡ljh NOI之后就退役了,然后就滚去学文化课了。
    他每天都被katarina大神虐,仗着自己学过一些姿势就给katarina大神出了一道题。
    有一棵 n 个节点的以 1 号节点为根的树,每个节点上有一个小桶,节点u上的小桶可以容纳

    个小球,ljh每次可以给一个节点到根路径上的所有节点的小桶内放一个小球,如果这个节点的小桶满了则不能放进这个节点,在放完所有小球之后就企图去刁难katarina大神,让katarina大神回答每个节点的小桶内的小球有多少种颜色。
    然而katarina大神一眼就秒掉了,还说这就是一道傻逼模板题。
    现在katarina大神想考考即将参加NOIP2019的你能不能回答上辣鸡ljh的问题。

    输入格式

    第一行,一个整数n,树上节点的数量。
    接下来n ? 1行,每行两个整数u, v,表示在u, v之间有一条边。
    接下来一行n个整数,

    ~

    表示每个节点上的小桶数量。
    下一行是一个整数m,表示ljh进行的操作数量。
    接下来m行,每行两个整数x, c,分别表示进行操作的节点和小球颜色。
    下一行是一个整数Q,表示你需要回答的询问数。
    接下来Q行,每行一个整数x,表示一个询问。

    输出格式

    对于每个询问输出一行表示这个询问的答案、

    样例

    样例输入1

    5
    1 2
    2 3
    3 4
    2 5
    2 1 1 1 1
    2
    2 1
    4 2
    3
    1
    3
    5 
    

    样例输出1

    2
    1
    0 
    

    样例输入2

    10
    3 10
    2 5
    3 2
    2 6
    1 9
    8 7
    7 4
    3 8
    3 1
    15 47 23 22 9 16 45 39 21 13
    10
    10 7
    9 3
    5 1
    5 2
    9 4
    10 9
    2 4
    10 1
    2 6
    7 9
    3
    1
    2
    3
    

    样例输出2

    7
    4
    6 
    

    数据范围与提示

    子任务

    image


     析:这道题的暴力很好想,在考场上我理论上能拿30分(看错题了。。。,颜色相同的点不算贡献,但是会算空间!!!),正解应该是线段树合并,这个先留着


    C. 大佬

    内存限制:512 MiB 时间限制:1000 ms 标准输入输出
    题目类型:传统 评测方式:文本比较
     

    题目描述

    辣鸡ljh NOI之后就退役了,然后就滚去学文化课了。
    他发现katarina大佬真是太强了,于是就学习了一下katarina大佬的做题方法。
    比如这是一本有n道题的练习册,katarina大佬每天都会做k道题。
    第一天做第1~k题,第二天做第

    ~ 题……第 天做第 ~

    道题。
    但是辣鸡 ljh 又不想太累,所以他想知道katarina大佬做完这本练习册的劳累度。
    每道题有它的难度值,假设今天katarina大佬做的题目中最大难度为t,那么今天katarina大佬的劳累度就是wt?,做完这本书的劳累值就是每天的劳累值之和。
    但是辣鸡ljh一道题都不会,自然也不知道题目有多难,他只知道题目的难度一定在1~m之间随机。
    他想让即将参加 NOIP 的你帮他算算katarina大佬做完这本书的劳累值期望

    输入格式

    第一行,三个整数


    第二行, 个整数表示

     

    输出格式

    输出劳累值期望对1000000007取模的值。

    样例

    样例输入1

    2 2 2
    1 2 
    

    样例输出1

    750000007
    

    样例1解释

    有{1,1},{1,2},{2,1},{2,2}四种可能,期望为

    样例输入2

    5 4 3
    2 1 3 5 
    

    样例输出2

    890625018
    

    数据范围与提示

    子任务

    image

    析:很明显的一道概率期望题,在考场上我想了2个小时左右,但是思路想偏了,我当时一直在想第 i 小的值作为最大值的概率,但是正解应该为 第 i 天的值作为最大值的概率 p=(x/m)^k , 具体来说就是 f[1]=(1\m)^k , f[2]=(2\m)^k-f[1] , f[3]=(3/m)^k-f[2]-f[1]......

    所以结果为 (i (1->m) sum(w[i]*f[i]) )*(n-k+1);

    注意最后取模的时候要先给 ans * inv ,再取模,不然会出错!!

    代码:

    #include<bits/stdc++.h>
    #define re register int
    #define D double
    #define int long long
    #define mo 1000000007
    using namespace std;
    const int N=610;
    int n,m,k,tot,cnt;
    int ans,inv,cj,s;
    int f[N],w[N],cf[N];
    int ksm(int d,int z)
    {
    	int out=1;
    	while(z)
    	{
    		if(z&1)
    			out=out*d%mo;
    		z>>=1;
    		d=d*d%mo;
    	}
    	return out;
    }
    #undef int
    int main()
    {
    	#define int long long
    	scanf("%lld%lld%lld",&n,&m,&k);
    	for(re i=1;i<=m;i++)
    		scanf("%lld",&w[i]);
    	if(k>n)
    	{
    		printf("0\n");
    		return 0;
    	}
    	cj=ksm(m,k);
    	inv=ksm(cj,mo-2);
    	for(re i=1;i<=m;i++)
    	{
    		f[i]=(ksm(i,k)-s)%mo;
    		s=s+f[i]%mo;
    	}
    	for(re i=1;i<=m;i++)
    		ans=(ans%mo+w[i]*f[i])%mo;
    	ans=((ans*inv)%mo*((n-k+1)%mo))%mo;
    	printf("%lld\n",(ans+mo)%mo);
    	return 0;
    }
    

    D. 宝藏

     

     


    析:看到数据范围,妥妥的状压dp,但是这道题是 dp+dfs,思路 f[j][(1<<(j-1))|s][deep+1]=min(sum+dis[i]*l[i][j]) , 表示将节点 j 放入集合 s 中,从 i (深度为deep)转移过来的最小值;

    注意在dfs 过程中要用两层 for 循环来枚举从哪里转移过来,并保存 dis[x],为经过的节点数,因为从哪个点转移来的不确定,所以这个值不能直接传到函数里!!

    注意dfs里四个剪枝优化,看似不起眼但是效果巨大!!

    代码:

    #include<bits/stdc++.h>
    #define re register int
    #define next net
    using namespace std;
    const int N=1010;
    const int INF=1e9;
    int n,m,tot,ans=INF;
    int l[15][15],f[15][1<<13][13];//!!!
    int to[15][15],dis[15];
    map<int,bool> p[15];
    void dfs(int s,int deep,int sum)
    {
    	if(sum>=ans)
    		return;
    	if(s==((1<<n)-1))
    	{
    		ans=min(ans,sum);
    		//cout<<"deep="<<deep<<" ans="<<ans<<endl;
    		return;
    	}
    	//int cun=0;
    	for(re i=1;i<=n;i++)
    	{
    		if(!(s&(1<<(i-1))))
    			continue;
    		for(re j=1;j<=n;j++)
    		{
    			if(s&(1<<(j-1)))
    				continue;
    			if(f[j][s|(1<<(j-1))][deep+1]<=sum+dis[i]*l[i][j])
    				continue;
    			if(!p[i][j])
    				continue;
    			f[j][s|(1<<(j-1))][deep+1]=sum+dis[i]*l[i][j];
    			//cout<<"i="<<i<<" j="<<j<<" f="<<f[j][s|(1<<(j-1))][deep+1]<<endl;
    			dis[j]=dis[i]+1;
    			dfs(s|(1<<(j-1)),deep+1,f[j][s|(1<<(j-1))][deep+1]);
    		}
    	}
    }
    int main()
    {
    	int a,b,c;
    	scanf("%d%d",&n,&m);
    	memset(l,127,sizeof(l));
    	for(re i=1;i<=m;i++)
    	{
    		scanf("%d%d%d",&a,&b,&c);
    		if(!p[a][b])
    		{
    			p[a][b]=1;
    			to[a][++to[a][0]]=b;
    			p[b][a]=1;
    			to[b][++to[b][0]]=a;
    		}
    		l[a][b]=min(l[a][b],c);
    		l[b][a]=l[a][b];
    	}
    	for(re i=1;i<=n;i++)
    	{
    		memset(f,127,sizeof(f));
    		memset(dis,0,sizeof(dis));
    		dis[i]=1;
    		//f[i][1<<(i-1)][1]=0;
    		dfs((1<<(i-1)),0,0);
    	}
    	printf("%d\n",ans);
    	return 0;
    }
    
  • 相关阅读:
    记录下IE7下的input标签bug
    CYQ.Data 轻量数据访问层(一) 概述
    网站安装打包 软件环境检测与安装[二] 上
    记录下关于调用RAR解压缩的问题
    CYQ.Data 轻量数据访问层(六) 构造数据表
    记绕过路由封杀问题
    MapXtreme 2005 学习心得 一些问题(八)
    网站安装打包 修改app.config[六]
    关于控件导出Excel格式问题的新解决方案
    CYQ.Data 轻量数据访问层(二) 构造数据单元(上)
  • 原文地址:https://www.cnblogs.com/WindZR/p/14872866.html
Copyright © 2020-2023  润新知