【CCF CSP记录】202312-2 因子化简

文章介绍了使用C++编程语言实现的埃拉托斯特尼筛法筛选素数,并利用unordered_map高效存储素因子及其出现次数,优化查找过程。通过示例展示了如何计算给定整数n的素因子,满足特定条件的因子个数。
摘要由CSDN通过智能技术生成

 

方法一

参考:

http://t.csdnimg.cn/IpJWP

http://t.csdnimg.cn/pBgNb

 思路

采用埃拉托斯特尼筛法(埃氏筛素数法)

  • 从2开始,将2的倍数标记为合数,然后找到下一个未被标记的数,将其倍数标记为合数,重复这个过程,直到达到预定范围。
  • 在每次标记过程中,未被标记的数即为质数。

这里需要知道这样一个素数原理:

任意的大于0整数,其质因子分解最多只有1个质因子大于 \sqrt{n},​ 且该因子一定是一次幂。因此只需要筛一下2~1000以内的素数即可。

#include<bits/stdc++.h>
using namespace std;
int q;
long long n,k,ans;
vector<long long> Sushu;
//判断素数  
void is_prime(){
	bool isPrime[1001];
	for(int i=2;i<=1000;i++){
		isPrime[i]=true;
	} 
	for(int i=2;i*i<=1000;i++){
		if(isPrime[i]){
			for(int j=i*i;j<=1000;j+=i){
				isPrime[j]=false;
			}
		}
	}
	for(int i=2;i<=1000;i++){
		if(isPrime[i]){
			Sushu.push_back(i);
		}
	}	
}

int main(){
	is_prime();
	cin>>q;
	while(q--){
		cin>>n>>k;
		ans=1;
		int flag=0,curK=0;
		while(n>1&&flag<Sushu.size()){
			if(n%Sushu[flag]==0){
				curK ++;
				n/=Sushu[flag];
			}else{
				if(curK<k){
					curK=0;
					flag++;
					continue;
				}
				for(int i=0;i<curK;i++){
					ans*=Sushu[flag];
				}
				curK=0;
				flag++;
			}
		}
		if(curK>=k){
			for(int i=0;i<curK;i++){
				ans*=Sushu[flag];
			}
		}
		cout<<ans<<endl;
	}
}

方法二

参考:http://t.csdnimg.cn/4URd0

关于unordered_map:

  1. unordered_map是一个将key和value关联起来的容器,它可以高效的根据单个key值查找对应的value。
  2. key值应该是唯一的,key和value的数据类型可以不相同。
  3. unordered_map存储元素时是没有顺序的,只是根据key的哈希值,将元素存在指定位置,所以根据key查找单个value时非常高效,平均可以在常数时间内完成。
  4. unordered_map查询单个key的时候效率比map高,但是要查询某一范围内的key值时比map效率低。
  5. 可以使用[]操作符来访问key值对应的value值。
     
思路

1、定义一个哈希表用来存储,key表示素因子,value表示该素因子的个数。

2、循环,从j=2开始依次向后判断,可以被n除尽则就是n的一个素因子,n也相应缩小j倍。maps用来记录。在此说明,除完2开始除3,然后是4,4一定不能被整除,因为如果能被4整除则一定会被2整除,后面的也是这样。

3、再说一下循环结束条件一定是n,n的大小一直在成倍的缩小,而除数的值永远都不能大于n,因此循环判断条件为j<=n。

4、最后根据阈值跳过那些不符合要求的素因子进行相乘。

关注这种思路中筛出素因子方法。

map.first是key值,map.second是value值

运行时在编译环境中加入以下内容,更改为c++11版本

#include<bits/stdc++.h>

using namespace std;
int main() {
    int q;
    cin >> q;
    for (int i = 0; i < q; ++i)
    {
        long long n, res = 1;
        int k;
        cin >> n >> k;
        unordered_map<int, int>maps;
        for (int j = 2; j <= n; ++j)
        {
            while (n % j == 0)
            {
                ++maps[j];//j对应的指数加一 
                n /= j;//n缩小 j倍 
            }
        }
        for (auto s : maps)
        {
            if (s.second < k)
                continue;
            res *= pow(s.first, s.second);
        }
        cout << res << endl;
    }
}

 结果

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值