CF1622F Quadratic Set
观察到答案的下界为 \(n-3\) ,
证明:
若 \(n\) 为偶数,令 \(k=\frac{n}{2}\)
\(\displaystyle \prod_{i=1}^{2k} i!=\left(\prod_{i=1}^k (2i-1)! \right)^22^kk!\)
- 当 \(k\) 为偶数时,删去 \(k\) 即可
- 当 \(k\) 为奇数时,删去 \(2,k\) 即可
若 \(n\) 为奇数,删去 \(n\) 转化为偶数的情况,最多删去 \(3\) 个数。
注意上述构造不一定是最优的,需要依次判断。
最后一个问题,如何快速判断一个数是否为完全平方数?
考虑异或哈希,将每一个质数 \(p\) 随机赋权 \(f(p)\) ,并规定 \(f(1)=0,f(ab)=f(a) \oplus f(b)\)
那么 \(x\) 为完全平方数 \(\Leftrightarrow\) \(f(x)=0\)
#include <bits/stdc++.h>
using namespace std;
#define ull unsigned long long
#define pii pair< int , int >
#define fi first
#define sc second
#define mp make_pair
ull rd( ) {
return ( rand() + 0llu ) | ( ( rand() + 0llu ) << 16llu ) | ( ( rand() + 0llu ) << 32llu ) | ( ( rand() + 0llu ) << 48llu );
}
const int MAXN = 1e6;
int prn , pri[ MAXN + 5 ]; bool vis[ MAXN + 5 ];
ull f[ MAXN + 5 ];
void sieve() {
f[ 1 ] = 0;
for( int i = 2 ; i <= MAXN ; i ++ ) {
if( !vis[ i ] ) pri[ ++ prn ] = i , f[ i ] = rd();
for( int j = 1 ; j <= prn && 1ll * i * pri[ j ] <= MAXN ; j ++ ) {
vis[ i * pri[ j ] ] = 1;
f[ i * pri[ j ] ] = f[ i ] ^ f[ pri[ j ] ];
if( i % pri[ j ] == 0 ) break;
}
}
for( int i = 1 ; i <= MAXN ; i ++ ) f[ i ] ^= f[ i - 1 ];
}
int n; ull hs;
unordered_map< ull , int > vish;
int main( ) {
srand( 123456 ); sieve();
scanf("%d",&n);
//n
for( int i = 1 ; i <= n ; i ++ ) hs ^= f[ i ];
if( hs == 0 ) {
printf("%d\n", n );
for( int i = 1 ; i <= n ; i ++ ) printf("%d ", i );
return 0;
}
//n-1
for( int i = 1 ; i <= n ; i ++ ) if( ( hs ^ f[ i ] ) == 0 ) {
printf("%d\n", n - 1 );
for( int j = 1 ; j <= n ; j ++ ) if( i != j ) printf("%d ", j );
return 0;
}
//n-2
for( int i = 1 ; i <= n ; i ++ ) {
if( vish[ f[ i ] ] ) {
printf("%d\n", n - 2 );
for( int j = 1 ; j <= n ; j ++ ) if( j != i && j != vish[ f[ i ] ] ) printf("%d ", j );
return 0;
}
vish[ hs ^ f[ i ] ] = i;
}
//n-3
assert( n & 1 );
printf("%d\n", n - 3 );
for( int i = 1 ; i <= n ; i ++ ) if( i != 2 && i != ( n - 1 ) / 2 && i != n ) printf("%d ", i );
return 0;
}