蓝桥云课-4861 坤坤的魔法游戏-题解

1.问题描述 

蓝桥账户中心icon-default.png?t=N7T8https://www.lanqiao.cn/problems/4861/learning/?page=1&first_category_id=1&tags=%E8%B4%A8%E6%95%B0%E7%AD%9B%E6%B3%95

在一个神秘的世界里,坤坤正在玩一个古老的魔法游戏。这个游戏的目标是将一些神秘的咒语石头分组。每个咒语石头都有一个独特的编号,范围是从 22 到 N。在每一步,坤坤可以选择两个独特的咒语石头,如果他们共享一个大于 11 的共同因子,就可以将它们归入同一组。坤坤会一直将石头进行分组,直到不能再进行分组为止。

在这个游戏中,归属于一个组的石头形成了等价关系。这意味着如果石头 a 和石头 b 在同一组,石头 b 和石头 c 也在同一组,那么石头 a 和石头 c 就被认为是在同一组。

坤坤的任务是找出最后形成的组的总数。

输入格式

第一行将包含一个整数 T,表示测试案例的数量。然后是 T 行输入,每行包含一个整数 N。

数据范围保证:1≤T≤2×105,2≤N≤107。

输出格式

对于每个测试案例,输出一行,表示最后形成的组的总数。

样例输入

3

2

4

8

样例输出

2

2

3

说明

测试案例 1:最后的组是 { 22 }。

测试案例 2:最后的组是 { 2,42,4 } 和 { 33 }。

测试案例 3:最后的组是 { 2,3,4,6,82,3,4,6,8 },{ 55 } 和 { 77 }。

2.算法分析和描述

(1)素数筛法和前缀和计算:使用埃氏筛法(Sieve of Eratosthenes)找出每个数的最小质因子(即最小素因子)。这个步骤的目的是为了快速判断数的质因子,以便后续的因子关系判断。同时,计算一个前缀和数组 a[],其中 a[i] 表示从 2 到 i 之间有多少个素数。这个数组帮助在 O(1) 时间内得到任意范围内的素数数量。

(2)因子关系判断:对于每个数 N,我们需要找出满足条件的数对 (i, j),其中 i 和 j 都大于 11,并且它们有共同的大于 11 的因子。

这可以通过数的质因子信息和欧几里得算法来实现。具体地,我们可以预先计算每个数的所有因子,并根据其最小质因子来判断两个数是否有共同的大于 11 的因子。

(3)计算组数:利用前面预处理的数据,对于每个测试案例中的 N,通过遍历可能的数对 (i, j) 来计算出最终的组数。每对 (i, j) 如果满足条件,将它们归入同一组。

3.实现代码

#include <iostream>
using namespace std;
const int MAX=10000001; 
int fac[MAX]={0},a[MAX]={0},num=0;   //num记录有多少个素数
 
void ai(){    //埃式筛法
  for(int i=2;i<MAX;++i){
  if(fac[i]==0)
    for(int j=i;j<MAX;j+=i)
    fac[j]=i;
  if(fac[i]==i) ++num;    //如果(fac[i]==i),则说明i是素数,更新num
  a[i]=num;  //a[i]存储从2到i之间有多少个素数
  }       //a[2]=1,a[3]=2,a[4]=2,a[5]=3,a[6]=3,a[7]=4
}
 
// a[6]-a[3]=3-2=1,代表着:2到6之间的素数(2,3,5)-2到3之间的素数(2,3)=3到6之间的素数(5)
 
int main()
{
  ai();    //初始化
  int T,N,sum;  //sum为总组数
  cin>>T;
  while(T--){    //T组测试用例
    cin>>N;
    sum=1;   //2~N/2的数和N/2~N的非素数为一组
    //if(N/2<2) --sum;  N==2||N==3的情况sum会多算一次 ,虽然测试用例没有
    sum+=a[N]-a[N/2];    //前缀和
    cout<<sum<<endl;
    }
  return 0;
}

  • 14
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值