首页 > 其他分享 >洛谷 P1161 开灯

洛谷 P1161 开灯

时间:2024-07-25 11:55:22浏览次数:7  
标签:小明 set 洛谷 int double 开灯 flag P1161 取整

目录

题目 - 开灯

题目描述

在一条无限长的路上,有一排无限长的路灯,编号为 1 , 2 , 3 , 4 , ······。

每一盏灯只有两种可能的状态,开或者关。如果按一下某一盏灯的开关,那么这盏灯的状态将发生改变。如果原来是开,将变成关。如果原来是关,将变成开。

在刚开始的时候,所有的灯都是关的。小明每次可以进行如下的操作:

指定两个数, a , t ( a 为实数, t 为正整数)。将编号为 ⌊a⌋ , ⌊2×a⌋ , ⌊3×a⌋ , … , ⌊t×a⌋ 的灯的开关各按一次。其中 ⌊k⌋ 表示实数 k 的整数部分。

在小明进行了 n 次操作后,小明突然发现,这个时候只有一盏灯是开的,小明很想知道这盏灯的编号,可是这盏灯离小明太远了,小明看不清编号是多少。

幸好,小明还记得之前的 n 次操作。于是小明找到了你,你能帮他计算出这盏开着的灯的编号吗?

输入格式

第一行一个正整数 n ,表示 n 次操作。

接下来有 n 行,每行两个数, ai , ti 。其中 ai 是实数,小数点后一定有 6 位, ti 是正整数。

输出格式

仅一个正整数,那盏开着的灯的编号。

样例 #1

样例输入 #1

3
1.618034 13
2.618034 7
1.000000 21

样例输出 #1

20

提示

记 T 为对 ti 求和的值,

  • 对于 30% 的数据,满足 T < 1000 ;
  • 对于 80% 的数据,满足 T < 200000 ;
  • 对于 100% 的数据,满足 T < 2000000 ;
  • 对于 100% 的数据,满足 n < 5000 , 1 < ai <1000 , 1 < ti < T 。

数据保证,在经过 n 次操作后,有且只有一盏灯是开的,不必判错。而且对于所有的 i 来说, ti * ai 的最大值不超过 2000000 。

AC CODE

思路

  • 题目的数据量 > 2e6 ,使用数组(array)是装不下的,而且最后遍历数组的时间复杂度也非常高
  • 因此总体思路是,使用某个结构,标记每次操作后出现变化的灯

使用 Map

  • 每次进行 map.find 操作,如果该灯已被标记,则翻转灯的状态,如果该灯未被标记,则将其打上 "已被点亮" 的标记
  • 遍历 map 中的元素,其中标记为 "点亮" 的灯为结果

使用 Set

  • 设定点亮的灯被放入 set 中,那么每次对被选中的灯进行 set.find 操作,如果 find 成功,表示灯需要被熄灭,则进行 set.erase 操作,如果 find 失败,则表示该灯需要被点亮,进行 set.insert 操作
  • 最后 set 中只会剩下被点亮的灯,在进行结果遍历时会更快

AC CODE

C++

#include <iostream>
#include <set>

using namespace std;

int main()
{
    int t;
    cin >> t;
    set<int> opare_set;
    while (t != 0)
    {
        double num;
        int k;
        cin >> num >> k;
        for (int i = 1; i <= k; i++)
        {
            int temp = (int)(1.0 * num * i);
            if (opare_set.find(temp) == opare_set.end())
            {
                opare_set.insert(temp);
            }
            else
            {
                opare_set.erase(temp);
            }
        }
        t--;
    }
    for (auto it : opare_set) {
        cout << it << endl;
    }
    return 0;
}

说明

使用 Map 做数据标记,会出现 TEL

  • 因为 set 的查找效率更高,它的增删改查时间复杂度都为 logN

    set 会对集合中的元素进行排序,set 的底层数据结构是红黑树(平衡二叉树),因此查找效率更高

  • 最后 set 中只会剩下被点亮的灯,在进行结果遍历时会更快

  • 和 Java 中 Set 容器的底层实现类似,Set 是一组只用 key 值的 Map 结构

在此附上使用 Map 之后 TEL 的代码

#include<bits/stdc++.h>
using namespace std;
int lowerN(double n) // 向下取整函数 
{
	return floor(n);
}
int main()
{
	int k;
	cin>>k;
	map <int,bool> flag; // map记录被改变状态的灯 
	for(int h=0;h<k;h++)
	{
		double a;
		int t;
		cin>>a>>t;
		for(int i=1;i<=t;i++)
		{
			int temp=1.0*a*i;
			temp=lowerN(temp);
			//迭代器 记录灯是否改变状态 
			map <int,bool>::iterator iterflag; 
			iterflag=flag.find(temp);
			if(iterflag==flag.end())
			{
				flag.insert(pair<int,bool>(temp,true));
			} 
			else
			{
				flag[temp]=!flag[temp];
			}
		}
	} 
	int anser;
	map <int,bool>::iterator iteranser;
	for(iteranser=flag.begin();iteranser!=flag.end();iteranser++)
	{
		if(iteranser->second==true)
		{
			anser=iteranser->first;
			break;
		}
	}
	cout<<anser<<endl;
	return 0;
} 

向下取整

  • 在 C/C++/Java 中,使用 (int) 等进行强制类型转换,计算机会采用丢失精度的方式进行强转,得到的结果就是保留了数值的整数位
  • 可以使用 <math.h> 头文件中的 floor 函数完成取整操作

<math.h> 中常用的函数

参考自以下文章

math.h头文件下的常用函数!取整,取绝对值,四舍五入......看这一篇就够了!

math.h - 百度百科

取整函数

  • floor(double x):向下取整函数,标准定义为取比 x 小的最大整数,因此 floor(-2.3) = -3
  • ceil(double x):向上取整函数,标准定义为取比 x 大的最小整数,因此 ceil(-2.3) = -2

取绝对值

  • abs(int x):对整型取绝对值
  • fabs(double x):对浮点型取绝对值
  • labs(long x):对长整型取绝对值

四舍五入

  • round(double x):四舍五入函数

运算

  • pow(double x, double y):幂函数,求 x 的 y 次方,当 y = 0.5,就是对 x 求平方根
  • log(double x):对数函数,求以 e 为底数 x 的对数
  • sqrt(double x):对 x 开平方函数,得到一个大于 0 的结果

标签:小明,set,洛谷,int,double,开灯,flag,P1161,取整
From: https://www.cnblogs.com/Muhuai/p/18322652

相关文章

  • 洛谷刷题题单
    【算法1-1】模拟与高精度 [NOIP2003普及组]乒乓球 [NOIP2003普及组]乒乓球......
  • 洛谷题单指南-前缀和差分与离散化-P8218 【深进1.例1】求区间和
    原题链接:https://www.luogu.com.cn/problem/P8218题意解读:对于数组a[N],给定m个区间l~r,求每个区间所有元素之和。解题思路:先思考暴力做法:对于每一个区间[l,r],累加a[l]~a[r]所有元素,时间复杂度最坏为10^5*10^4,不可行。一维前缀和:设s[N]是a[N]的前缀和数组,即对于每一个s[i......
  • 线段树(区间操作,例题:洛谷P3372 线段树 1)
    在上一节线段树(原理、构造和区间查询,例题:BalancedLineup)中介绍了线段树的构造,下面就来说一下它的区间操作。区间操作与Lazy-Tag有关,如果修改操作是对区间内的每个元素一一修改,就会比较繁琐低效,目前的解决办法是线段树的tree[i].data记录的是区间i的值(详细见上节),可以再定义一......
  • 洛谷P1029 [NOIP2001 普及组] 最大公约数和最小公倍数问题
    [NOIP2001普及组]最大公约数和最小公倍数问题题目描述洛谷题目链接:https://www.luogu.com.cn/problem/P1029输入两个正整数x,y,求出满足下列条件的P,Q的个数:P,Q是正整数。要求P,Q以x为最大公约数,以y为最小公倍数。试求:满足条件的所有可能的P,Q的个数。......
  • [NOIP2008 提高组] 笨小猴(洛谷题号P1125)
    [NOIP2008提高组]笨小猴题目描述笨小猴的词汇量很小,所以每次做英语选择题的时候都很头疼。但是他找到了一种方法,经试验证明,用这种方法去选择选项的时候选对的几率非常大!这种方法的具体描述如下:假设maxn是单词中出现次数最多的字母的出现次数,minn是单词中出现次数最少的字母的......
  • 洛谷P10693
    洛谷P10693好奇怪的题目编号题面\(n\)个人,\(2n\)个座位,每个人都有心仪的座位,如\(i\)心仪的座位为\(a_i\)(可重复),设计师设计让他们坐在自己编号的位置上,即\(i\)做到\(i\),每个人只可以做\(a_i\)或\(i\),最多多少个人坐到心仪的座位。思路提取input11213453799111112......
  • 洛谷算法题
    目录数字反转迪杰斯特拉算法背包问题字符串排序P1192台阶问题P1111修复公路炸铁路问题计数问题......
  • 洛谷P1331 海战
    一、题目题目背景在峰会期间,武装部队得处于高度戒备。警察将监视每一条大街,军队将保卫建筑物,领空将布满了F-2003飞机。此外,巡洋船只和舰队将被派去保护海岸线。不幸的是,因为种种原因,国防海军部仅有很少的几位军官能指挥大型海战。因此,他们培养了一些新海军指挥官。军官们......
  • 2024 洛谷月赛(柒)
    月赛GGrun%%%T1在相思树下I签到题QWQ,找规律易得。证明未知每次一定会删掉一半的数,所以第\(i\)次操作都会提供一个\(1<<i-1\)的贡献。这个贡献就是下一次会往后跳多少个位置。假如一开始确定留下的是第一个,那删偶数不会有影响,而删奇数需要往后跳。code#include<bit......
  • hi.开灯
    开灯题目背景该题的题目是不是感到很眼熟呢?事实上,如果你懂的方法,该题的代码简直不能再短。但是如果你不懂得呢?那。。。(自己去想)题目描述首先所有的灯都是关的(注意是关!),编号为11......