线性筛法
#include <bits/stdc++.h>
using namespace std;
const int N= 1e7 ;
bool flag[ N+ 10 ] ;
int prime[ N+ 10 ] ;
int main ( )
{
memset ( flag, 1 , sizeof ( flag) ) ;
flag[ 0 ] = 0 ; flag[ 1 ] = 0 ;
int index= 0 ;
for ( int i= 2 ; i<= N; i++ )
{
if ( flag[ i] ) prime[ index++ ] = i;
for ( int j= 0 ; j< index&& prime[ j] * i<= N; j++ )
{
flag[ prime[ j] * i] = 0 ;
if ( i% prime[ j] == 0 ) break ;
}
}
return 0 ;
}
复杂度为O(n),得到素数集合prime[],flag[i]判断i是不是素数,也可以让flag[i]=index+1,flag的值就保存了i是第几个素数
这题好难哦,解题思路:唯一分解定理:举个例子:18的因子和
素因子为33 2,因子和为(3^2 + 3^1 + 3^0) * (2^1 +2^0)=39
所以可以用一个二维数组(或者结构体)把素因子及其幂存起来,最后用等比数列求和公式a1*(q^n-1)/(q-1),a1都是1
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int prime[ 78500 ] ;
bool f[ 1000000 ] ;
const int N= 1e6 ;
void data ( )
{
int cnt= 0 ;
memset ( f, 1 , sizeof ( f) ) ;
for ( int i= 2 ; i< N; i++ )
{
if ( f[ i] ) prime[ cnt++ ] = i;
for ( int j= 0 ; j< cnt&& prime[ j] * i< N; j++ )
{
f[ i* prime[ j] ] = 0 ;
if ( i% prime[ j] == 0 ) break ;
}
}
}
ll quick ( ll a, int n)
{
ll ans= 1 ;
while ( n)
{
if ( n& 1 ) ans= ans* a;
n>>= 1 ;
a= a* a;
}
return ans;
}
int main ( )
{
data ( ) ;
int t, n;
scanf ( "%d" , & t) ;
while ( t-- )
{
int a[ 20 ] [ 2 ] , cnt= 0 , i= 0 ;
scanf ( "%d" , & n) ;
while ( n!= 1 && i<= 3401 )
{
if ( n% prime[ i] == 0 )
{
a[ cnt] [ 1 ] = 0 ;
while ( n% prime[ i] == 0 )
{
n/ = prime[ i] ;
a[ cnt] [ 1 ] ++ ;
}
a[ cnt++ ] [ 0 ] = prime[ i] ;
}
i++ ;
}
if ( n!= 1 )
{
a[ cnt] [ 1 ] = 1 ;
a[ cnt++ ] [ 0 ] = n;
}
ll ans= 1 ;
for ( int i= 0 ; i< cnt; i++ )
{
ans* = ( quick ( ( ll) a[ i] [ 0 ] , a[ i] [ 1 ] + 1 ) - 1 ) / ( a[ i] [ 0 ] - 1 ) ;
}
printf ( "%lld\n" , ans) ;
}
return 0 ;
}
变化不大,简单题
#include <bits/stdc++.h>
using namespace std;
const int N= 1e7 ;
bool flag[ N+ 10 ] ;
int prime[ N+ 10 ] ;
int main ( )
{
memset ( flag, 1 , sizeof ( flag) ) ;
int index= 0 ;
flag[ 1 ] = 0 ;
flag[ 0 ] = 0 ;
for ( int i= 2 ; i<= N; i++ )
{
if ( flag[ i] ) prime[ index++ ] = i;
for ( int j= 0 ; j< index&& prime[ j] * i<= N; j++ )
{
flag[ prime[ j] * i] = 0 ;
if ( i% prime[ j] == 0 ) break ;
}
}
int n;
while ( ~ scanf ( "%d" , & n) )
{
if ( flag[ n] ) printf ( "YES\n" ) ;
else printf ( "NO\n" ) ;
}
return 0 ;
}
也变化不大,依次去掉最高位,判断是不是素数
#include <bits/stdc++.h>
using namespace std;
int a[ 1000005 ] , b[ 1000005 ] ;
int main ( )
{
int n, m, cnt;
memset ( a, 1 , sizeof ( a) ) ;
for ( int i= 2 ; i<= 1000000 ; i++ )
{
if ( a[ i] != 0 )
for ( int j= 2 ; i* j<= 1000000 ; j++ ) a[ i* j] = 0 ;
}
cnt= 0 ;
for ( int i= 2 ; i<= 1000000 ; i++ )
{
if ( a[ i] != 0 ) b[ ++ cnt] = i;
}
while ( cin>> n)
{
int sum= 0 ;
if ( n== 1 ) { cout<< "0" << endl; continue ; }
for ( int i= cnt; i>= 1 ; i-- )
{
if ( n% b[ i] == 0 ) { cout<< i<< endl; break ; }
}
}
return 0 ;
}
发现组数多的时候,cin和cout都挺占时间的,一开始用cout都tle了
#include <bits/stdc++.h>
using namespace std;
const int N= 1e6 ;
bool flag[ N+ 10 ] ;
int prime[ N+ 10 ] ;
int main ( )
{
int n;
memset ( flag, 1 , sizeof ( flag) ) ;
int index= 0 ;
for ( int i= 2 ; i< N; i++ )
{
if ( flag[ i] ) prime[ index++ ] = i;
for ( int j= 0 ; j< index&& prime[ j] * i< N; j++ )
{
flag[ prime[ j] * i] = 0 ;
if ( i% prime[ j] == 0 ) break ;
}
}
flag[ 0 ] = 0 , flag[ 1 ] = 0 ;
while ( ~ scanf ( "%d" , & n) )
{
if ( ! flag[ n] ) { printf ( "NO\n" ) ; continue ; }
int A= 1e5 ;
int flag0= 1 ;
for ( int i= 0 ; ; i++ )
{
n= n% A;
if ( ! flag[ n] ) { flag0= 0 ; break ; }
A= A/ 10 ;
if ( n< 10 ) break ;
}
if ( flag0== 1 ) printf ( "YES\n" ) ;
else printf ( "NO\n" ) ;
}
return 0 ;
}
}
这题卡时间,思路:两个素数相乘小于N,用数组标记,一重循环小于sqrt(N),可以避免重复,减少时间
#include <bits/stdc++.h>
using namespace std;
const int N= 1e6 ;
int flag[ N+ 10 ] ;
int prime[ N+ 10 ] ;
int flag0[ N] ;
int main ( )
{
memset ( flag, 1 , sizeof ( flag) ) ;
int index= 0 ;
for ( int i= 2 ; i< N; i++ )
{
if ( flag[ i] ) { prime[ index++ ] = i; flag[ i] = index; }
for ( int j= 0 ; j< index&& prime[ j] * i< N; j++ )
{
flag[ prime[ j] * i] = 0 ;
if ( i% prime[ j] == 0 ) break ;
}
}
flag[ 1 ] = 0 ;
int n;
for ( int i= 0 ; prime[ i] < sqrt ( N* 1.0 ) ; i++ )
{
for ( int j= i; prime[ j] * prime[ i] < N; j++ )
{
flag0[ prime[ j] * prime[ i] ] = 1 ;
}
}
while ( ~ scanf ( "%d" , & n) )
{
if ( flag0[ n] ) printf ( "YES\n" ) ;
else printf ( "NO\n" ) ;
}
return 0 ;
}
用到一个小技巧flag[n]本来是用来判断是否是素数的,可以让flag也存上这个素数是第几个素数,然后找x开始为素数的下标与y+1开始的下标,相减就是之间的素数个数
#include <bits/stdc++.h>
using namespace std;
const int N= 2e6 ;
int flag[ N+ 10 ] ;
int prime[ N+ 10 ] ;
int main ( )
{
memset ( flag, 1 , sizeof ( flag) ) ;
int index= 0 ;
for ( int i= 2 ; i< N; i++ )
{
if ( flag[ i] ) { prime[ index++ ] = i; flag[ i] = index; }
for ( int j= 0 ; j< index&& prime[ j] * i< N; j++ )
{
flag[ prime[ j] * i] = 0 ;
if ( i% prime[ j] == 0 ) break ;
}
}
flag[ 1 ] = 0 ;
int x, y, sum;
while ( ~ scanf ( "%d %d" , & x, & y) )
{
sum= 0 ;
int i, j;
for ( i= x; ; i++ )
{
if ( flag[ i] ) { i= flag[ i] ; break ; }
}
for ( j= y+ 1 ; ; j++ ) if ( flag[ j] ) { j= flag[ j] ; break ; }
sum= j- i;
cout<< sum<< endl;
}
return 0 ;
}
判断1e14大小的素数的方法:用线性筛求出1e7以内的素数再判断这个数能否被前面的素数整除,不能则是素数
#include <bits/stdc++.h>
using namespace std;
const int N= 1e7 ;
bool flag[ N+ 10 ] ;
int prime[ N+ 10 ] ;
int su ( long long n)
{
int flag= 0 ;
for ( int i= 0 ; prime[ i] <= sqrt ( 1.0 * n) ; i++ )
{
if ( n% prime[ i] == 0 ) { flag= 1 ; break ; }
}
if ( n== 1 ) flag= 1 ;
return flag;
}
int main ( )
{
memset ( flag, 1 , sizeof ( flag) ) ;
int index= 0 ;
for ( int i= 2 ; i< N; i++ )
{
if ( flag[ i] ) prime[ index++ ] = i;
for ( int j= 0 ; j< index&& prime[ j] * i< N; j++ )
{
flag[ prime[ j] * i] = 0 ;
if ( i% prime[ j] == 0 ) break ;
}
}
int n;
scanf ( "%d" , & n) ;
long long a, b, c, sum;
while ( n-- )
{
scanf ( "%lld %lld %lld" , & a, & b, & c) ;
sum= a+ b- c;
if ( su ( sum) == 0 ) printf ( "yes\n" ) ;
else printf ( "no\n" ) ;
}
return 0 ;
}
这题非常简单就是套模板就行
#include <bits/stdc++.h>
using namespace std;
const int N= 1e7 ;
bool flag[ N+ 10 ] ;
int prime[ N+ 10 ] ;
int main ( )
{
memset ( flag, 1 , sizeof ( flag) ) ;
int index= 0 ;
for ( int i= 2 ; i< N; i++ )
{
if ( flag[ i] ) prime[ index++ ] = i;
for ( int j= 0 ; j< index&& prime[ j] * i< N; j++ )
{
flag[ prime[ j] * i] = 0 ;
if ( i% prime[ j] == 0 ) break ;
}
}
int n, q;
scanf ( "%d %d" , & n, & q) ;
int a;
while ( q-- )
{
scanf ( "%d" , & a) ;
printf ( "%d\n" , prime[ a- 1 ] ) ;
}
return 0 ;
}