信息学奥赛一本通 2082:【21NOIP提高组】报数 | 洛谷 P7960 [NOIP2021] 报数
【题目链接】
ybt 2082:【21NOIP提高组】报数
洛谷 P7960 [NOIP2021] 报数
【题目考点】
1. 筛法求质数
2. 因数
3. 数字拆分
4. 链表思想
【解题思路】
根据新的规则,任何一个十进制中某一位含有7的数字的倍数都不能报出来。
那么不能报出来的数字一定存在某一位是7的因数。
该题核心点为:如何判断一个数字的所有因数中,存在因数某一位是7。简单说成:判断某数字的因数中是否包含7。
解法1:枚举(70分)
has7函数:使用数字拆分的方法判断一个数字中是否有一位为7(是否包含7)。
设函数fac7,fac7(n)返回值表示n的因数中是否包含7。
- 先枚举出n的所有因数,可以枚举所有满足i≤ni\le \sqrt{n}i≤n的i,如果n能整除i,那么i及n/i都是n的因数。
- 用has7函数判断n的因数中是否包含7,如果存在包含的情况,那么fac7函数返回true。如果不存在包含7的情况,返回false。
主函数中,对于每次输入的x,
- 如果x的因数中包含7,那么输出-1。
- 否则从x+1开始,不断判断后面的每个数字的因数中是否包含7。如果找到某个数字的因数中不包含7,那么就输出这个数字。
has7的复杂度为O(logn)O(log n)O(logn),fact7的复杂度为O(n⋅logn)O(\sqrt{n}\cdot log n)O(n⋅logn),询问次数T最大为10510^5105,输入的x最大为10710^7107。极端情况下,要对每个数字判断一下它的因数中是否有7,复杂度为O(nn⋅logn)O(n\sqrt{n}\cdot log n)O(nn⋅logn),在n达到10710^7107时,总运算次数一定会超过10810^8108,会超时。
实际情况,用该方法写出代码提交,可以得70分。
解法2:筛法(100分)
该问题要做10510^5105次的询问,如果预先确定了每个可能的数字的的因数中是否包含7,那么每次询问的复杂度为O(1)O(1)O(1)。
类比判断多次询问的数字是不是质数的问题,可以通过筛法求质数表,而后询问的方法来减少复杂度。本题也可以采用类似的筛法。
设数组fac7,fac7[i]
表示数字i的因数中是否包含7,数组所有元素初值都为false。
显然fac7[1]
为false,i从2开始循环到10710^7107
- 如果
fac7[i]
为true,则略过。 - 如果
fac7[i]
为false,那么使用has7函数判断数字i中是否某一位是7。如果是,那么对所有满足i≤107i\le 10^7i≤107的i的倍数j,都把fac7[j]
设为true。
对于输入的x,如果x的因数包含7,即fac7[x]
为真,那么输出-1。
否则,要输出x的下一个因数包含7的数字。如果在这里枚举x后的每个数字看其因数是否包含7,则复杂度过高。
这里可以设一个链式结构,设数组nextNot7,nextNot7[i]
表示数字i的下一个因数不包含7的数字。该数组的值可以在做筛法的过程中生成,具体见代码注释。
在生成该数组后,x的下一个因数不包含7的数字就是nextNot7[x]
。
【注意】输入的x可以是10710^7107,而10710^7107是一个因数不包含7的数字,它的下一个因数不包含7的数字是100000011000000110000001,因此在做筛法时,最后一次循环时i应该是10000001,使得nextNot7[10000000]
为10000001才可以。
【题解代码】
解法1:枚举(70分)
#include <bits/stdc++.h>
using namespace std;
bool has7(int n)//判断数字n的某一位中是否有数字7
{for(int a = n; a > 0; a /= 10)//n都是正整数,可以用for循环 if(a%10 == 7)return true;return false;
}
bool fac7(int n)//判断数字n是否有因数中包含7
{for(int i = 1; i*i <= n; ++i)if(n%i == 0 && (has7(i) || has7(n/i)))return true;return false;
}
int main()
{int t, x, r;scanf("%d", &t);while(t--){scanf("%d", &x);if(fac7(x))printf("-1\n");else{for(r = x+1; fac7(r); ++r);//如果r因数中有7,就看下一个数字。直到找到一个因数中没有7的数字。 printf("%d\n", r);}}return 0;
}
解法2:筛法(100分)
#include <bits/stdc++.h>
using namespace std;
#define N 10000000
bool fac7[N+2];//fac7[i]:数字i的因数中某一位是否包含7
int nextNot7[N];//lastNot7[i]:数字i向后找第1个因数中不包含7的数字
bool has7(int n)//判断数字n的某一位中是否有数字7
{for(int a = n; a > 0; a /= 10)//n都是正整数,可以用for循环 if(a%10 == 7)return true;return false;
}
void screen()//普通筛法
{int lastNot7 = 1;//上一个因数中不包含7的数字 for(int i = 2; i <= N+1; ++i){if(fac7[i] == false)//如果还没有判断i{if(has7(i))//如果i中某一位包含7 { for(int j = i; j <= N; j += i)//i的所有倍数的因数中都包含7 fac7[j] = true;}else//确定i的因数不包含7 {nextNot7[lastNot7] = i;//lastNot7的下一个不包含7的数字是i lastNot7 = i;//lastNot7变为i }}}
}
int main()
{int t, x, i;screen();//筛法得到fac7scanf("%d", &t);while(t--){scanf("%d", &x);if(fac7[x])printf("-1\n");elseprintf("%d\n", nextNot7[x]);}return 0;
}
信息学奥赛一本通 2082:【21NOIP提高组】报数 | 洛谷 P7960 [NOIP2021] 报数相关推荐
- 洛谷 P7960 [NOIP2021] 报数
PS:如果读过题了可以跳过题目描述直接到题解部分 提交链接:洛谷 P7960 [NOIP2021] 报数 题目 题目描述 报数游戏是一个广为流传的休闲小游戏.参加游戏的每个人要按一定顺序轮流报数,但如 ...
- 2017提高组D1T1 洛谷P3951 小凯的疑惑
洛谷P3951 小凯的疑惑 原题 题目描述 小凯手中有两种面值的金币,两种面值均为正整数且彼此互素.每种金币小凯都有 无数个.在不找零的情况下,仅凭这两种金币,有些物品他是无法准确支付的.现在小 凯想 ...
- NOIP 提高组 2012 / 洛谷P1080 国王游戏 题解
题面: 略 简易题解: 假设第iii位大臣左手为LiL_{i}Li, 右手的数为R_{i} 并且我们有两位大臣iii,jjj,考虑他们的相对位置 (PPP 是 iii , jjj 之前的左手数值累乘 ...
- 信息学奥赛一本通 提高篇 第六部分 数学基础 相关的真题
第1章 快速幂 1875:[13NOIP提高组]转圈游戏 信息学奥赛一本通(C++版)在线评测系统 第2 章 素数 第 3 章 约数 第 4 章 同余问题 第 5 章 矩阵乘法 第 6 章 ...
- 信息学奥赛一本通(C++版)NOIP提高组(1820-1829)
信息学奥赛一本通(C++版)NOIP提高组目录 //1820 [题目描述] 我们可以用这样的方式来表示一个十进制数:将每个阿拉伯数字乘以一个以该数字所 处位置的(值减1)为指数,以10为底数的幂之和的 ...
- 《信息学奥赛一本通 提高篇》
提高篇 第一部分 基础算法 第1章 贪心算法 提高篇 第一部分 基础算法 第1章 贪心算法_青少年趣味编程-CSDN博客 提高篇 第一部分 基础算法 第1章 贪心算法 提高篇 第一部分 基础算法 第1 ...
- 信息学奥赛一本通 提高篇 第六部分 数学基础 第1章 快速幂
信息学奥赛一本通 提高篇 第六部分 数学基础 第1章 快速幂 https://blog.csdn.net/mrcrack/article/details/82846727 快速幂取模算法如何实现? h ...
- 《信息学奥赛一本通提高篇》第6章 组合数学
例1 计算系数(NOIP2011提高) 信息学奥赛一本通(C++版)在线评测系统 NOIP2011计算系数_nanhan27的博客-CSDN博客 「NOIP2011」 计算系数 - 组合数_TbYan ...
- 信息学奥赛一本通 提高篇 第一部分 基础算法 第2章 二分与三分
信息学奥赛一本通 提高篇 提高版 第一部分 基础算法 第2章 二分与三分 信息学奥赛一本通 提高篇 提高版 第一部分 基础算法 第2章 二分与三分_mrcrack的博客-CSDN博客_信息学奥赛一本通 ...
最新文章
- Cissp-【第1章 安全和风险管理】-2020-12-07(32页-58页)
- 介绍一下《windows安全性编程》之一
- SpringBoot 项目模板:摆脱步步搭建
- 拼多多“京东化”:自建物流重农卖菜是赚谁的钱?
- 简历石沉大海、面试被刷?拒绝你的HR小姐姐,可能只是个AI
- 单片机定时器精准定时_PIC单片机的定时器精准计时的计算
- 【Python学习】 - sklearn - 用于生成数据的make_blobs模块
- 斜视术后融合训练方法_做斜视手术两年后又复发了怎么办?
- java se 7u67_Java SE 7u72和Java SE 7u71有什么不同
- 从实例入手,讲解 CMake 的常见用法。demo1-demo8
- python中pandas数据分析基础3(数据索引、数据分组与分组运算、数据离散化、数据合并)...
- 作为产品经理,懂接口是必须的
- [MAR DASCTF明御攻防赛]enjoyit_1
- 算法/贪心算法/FractionalKnapsack部分背包问题
- 计算机组成存储单元地址分配,主存中存储单元地址的分配
- 实时游戏对战引擎MatchVS,我的对战旅程
- 组合数学与计算机科学书籍,计算机科学丛书:组合数学(原书第5版)
- Sublime修改成为Python编辑器,设置系统环境变量
- 下载 线代 薛威_考研线代李永乐真的首选吗?
- php数字和字母互换,PHP实现十进制数字与二十六进制字母串相互转换操作示例