题目链接:

codeforces 449C


题目大意:

对1~n的自然数构成数对,每个数对中的两个数不互质,问最多能得到多少组数对。


题目分析:

  • 对于每个大于2的素数,我们枚举它的倍数,得到个数,如果的得到的个数是奇数,我们可以通过舍去2*p这个数,得到正好偶数个,正好凑出数对,这样的方案一定是最优的。因为没有造成浪费。
  • 然后剩下2的倍数的数再进行组合,得到的就是最优解。

AC代码:

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#define MAX 100007

using namespace std;

typedef pair<int,int> PII;

int n;
int mark[MAX];
vector<int> prime;
vector<PII> pp;
stack<int> temp;

void init ( )
{
    prime.clear();
    memset ( mark , -1 , sizeof ( mark ) );
    for ( int i = 2 ; i < MAX ; i++ )
    {
        if ( ~mark[i] ) continue;
        prime.push_back ( i );
        for ( int j = 2*i ; j < MAX ; j += i )
            mark[j] = i;
    }
}

int main ( )
{
    init ( );
    while ( ~scanf ( "%d" , &n ) )
    {
        memset ( mark , 0 , sizeof ( mark ) );
        int ans = 0;
        pp.clear();
        for ( int i = 1 ; i < prime.size() ; i++ )
        {
            int x = prime[i];
            if ( x > n ) break;
            while ( !temp.empty() ) temp.pop();
            int num = 1;
            mark[x] = 1;
            temp.push ( x );
            for ( int j = 3*x ; j <=n ; j+= x )
            {
                if ( mark[j] ) continue;
                mark[j] = 1;
                temp.push ( j );
                num++;
            }
            if ( num&1 && 2*x <= n )
            {
                temp.push ( 2*x );
                mark[2*x] = 1;
            }
            while ( temp.size() > 1 )
            {
                int a = temp.top();
                temp.pop();
                int b = temp.top();
                temp.pop();
                pp.push_back ( make_pair ( a , b ) );
            }
        }
        while ( !temp.empty() ) temp.pop();
        int num = 0;
        for ( int i = 2 ; i <= n ; i += 2 )
        {
            if ( mark[i] ) continue;
            temp.push ( i );
            mark[i] = 1;
        }
        while ( temp.size() > 1 )
        {
            int a = temp.top();
            temp.pop();
            int b = temp.top();
            temp.pop();
            pp.push_back ( make_pair ( a , b ) );
        }
        printf ( "%d\n" , pp.size() );
        for ( int i = 0 ; i < pp.size() ; i++ )
            printf ( "%d %d\n" , pp[i].first , pp[i].second );
    }
}