Codeforces 449C - Jzzhu and Apples / 450E - Jzzhu and Apples

本文详细解析了一种基于素数的匹配算法实现过程,重点介绍了如何通过线性筛素数来寻找可以匹配的数对,并提供了完整的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先是官方题解:

Firstly, we should notice that 1 and the primes larger than N / 2 can not be matched anyway, so we ignore these numbers.

Let's consider each prime P where 2 < P ≤ N / 2. For each prime P, we find all of the numbers which are unmatched and have a divisor P. Let M be the count of those numbers we found. If M is even, then we can match those numbers perfectly. Otherwise, we throw the number 2P and the remaining numbers can be matched perfectly.

Finally, only even numbers may be unmatched and we can match them in any way.

这道题做了挺久了,今天纠结于另外一道题,想想还是先回顾一下= =。这道题没看题解前确实没什么思路,主要是每次看到好像和数论相关的就会吓住,其实这种题主要是思维性的,和知识关联并不大。主要这道题记录下来是线性筛素数每次还得去网上找模板,其实挺简单的,多用几次就熟练了。这道题解什么的官方题解写的很清楚,没什么好说的了。
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#include <deque>
using namespace std;
const int maxn = 100010;
#define MAX 100000
int prime[maxn],cnt,vis[maxn];
void init_prim()
{
	memset(vis,0,sizeof(vis));
	cnt = 0;
	for (int i = 2; i <= MAX; ++i)
	{
		if (!vis[i])
			prime[cnt++] = i;
		for (int j = 0; (j<cnt)&&(i*prime[j] <= MAX);  ++j)
		{
			vis[i*prime[j]] = 1;
			if(i%prime[j] == 0) break;
		}
	}
}
int flag[maxn],ans;
int save[maxn][2],pre,cache;
int main()
{
    int n;
    init_prim();
    //cout<<cnt<<endl;
    scanf("%d",&n);
    memset(flag,0,sizeof(flag));
    ans = 0;
    int temp;
    for(int i = 1;i<cnt;i++)
    {
        if(prime[i]>n/2)
            break;
        temp = 0;
        int fac = 1;
        while(fac*prime[i]<=n)
        {
            if(!flag[fac*prime[i]])
            {
                flag[fac*prime[i]] = 1;
                temp++;
                if(temp>2&&temp%2==0)
                {
                    save[ans][0] = fac*prime[i];
                    save[ans][1] = cache;
                    ans++;
                }
                cache = fac*prime[i];
            }
            fac++;
        }
        if(temp%2==1){
            flag[2*prime[i]] = 0;
            temp--;
            save[ans][0] = prime[i];
            save[ans][1] = cache;
            ans++;
        }
        else
        {
            save[ans][0] = prime[i];
            save[ans][1] = 2*prime[i];
            ans++;
        }
    }
    temp = 0;
    for(int i = 2;i<=n;i+=2)
    {
        if(!flag[i])
        {
            flag[i] = 1;
            temp++;
            if(temp%2==0)
            {
                save[ans][0] = i;
                save[ans][1] = cache;
                ans++;
            }
            cache = i;
        }
    }
    cout<<ans<<endl;
    for(int i = 0;i<ans;i++)
    {
        printf("%d %d\n",save[i][0],save[i][1]);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值