信息学奥林匹克数学竞赛,真不是吹的
建议多看看各种数学书,多get一点技巧(离散数学,具体数学等等)
#include
#include
#include
#include
#include
using namespace std ;
const int mmod = 1e9 + 7 , N = 5000 ;
int C[5005][5005] , fac[100005] , inv[100005] , D[100005] ;
int p[1000005] , phi[1000005] , miu[1000005] , tao[1000005] , d[1000005] , topp ;
bool isnotp[1000005] ;
void get_P(){
phi[1] = 0 ;
miu[1] = 1 ;
for( int i = 2 ; i <= 1000000 ; i ++ ){
if( !isnotp[i] ){
p[++topp] = i ;
phi[i] = i - 1 ;
miu[i] = -1 ;
tao[i] = 2 , d[i] = 1 ;
}
for( int j = 1 ; j <= topp && i * p[j] <= 1000000 ; j ++ ){
if( i % p[j] == 0 ){
//i中包含 p[j] ,现在又多了一个 p[j]
//也就是原来 i 和它互质的数,记为 k ,现在变成了 1*k,2*k,3*k...p[j]*k
//而这些 1*k,2*k,3*k...p[j]*k 一定和 i*p[j]互质
//http://blog.csdn.net/Lytning/article/details/24432651
phi[ i*p[j] ] = phi[i] * p[j] ;
//miu根据定义可得
miu[ i*p[j] ] = 0 ;
//num = p1^t1 + p2^t2 + ... + pn^tn ;
//tao[num] = ( t1 + 1 ) * ( t2 + 1 ) * ... * ( tn + 1 ) ;
//tao[ num*p[j] ] = tao[num] / ( d[i] + 1 ) * ( d[i] + 1 + 1 ) ;
tao[ i*p[j] ] = tao[i] / ( d[i] + 1 ) * ( d[i] + 2 ) ;
d[ i*p[j] ] = d[i] + 1 ;
break ;
}
phi[ i*p[j] ] = phi[i] * phi[ p[j] ] ;
miu[ i*p[j] ] = miu[i] * -1 ;
tao[ i*p[j] ] = tao[i] * 2 ;
d[ i*p[j] ] = 1 ;
}
}
}
//杨辉三角:C[i][j] = C[i-1][j] + C[i-1][j-1]
void preWork_C() {
C[0][0] = 1 ;
for( int i = 1 ; i <= 5000 ; i ++ ) {
C[i][0] = 1 ;
for( int j = 1 ; j <= i ; j ++ )
C[i][j] = ( C[i-1][j] + C[i-1][j-1] ) %mmod ;
}
}
//阶乘:fac[i] = fac[i-1] * i
void preWork_fac() {
fac[0] = 1 ;
for( int i = 1 ; i <= 100000 ; i ++ )
fac[i] = 1LL * fac[i-1] * i %mmod ;
}
//错排公式:D[i] = ( i - 1 )*( D[i-1] + D[i-2] )
void preWork_cuopai() {
D[1] = 0 ; D[2] = 1 ;
for( int i = 3 ; i <= 100000 ; i ++ )
D[i] = 1LL * ( i - 1 ) * ( D[i-1] + D[i-2] ) %mmod ;
}
//
int gcd( int a , int b ) {
if( !b ) return a ;
return gcd( b , a%b ) ;
}
//
long long exgcd( long long a , long long b , long long &x , long long &y ) {
if( !b ) {
x = 1 , y = 0 ;
return a ;
} else {
long long xx , yy , d = exgcd( b , a%b , xx , yy ) ;
x = yy , y = xx - a / b * yy ;
return d ;
}
}
//只有x和p互质时,才存在逆元
int get_inv( int x , int p ) {
long long inv , tmp ;
exgcd( x , p , inv , tmp ) ;
return ( inv %mmod + mmod ) %mmod ;
}
//同上,阶乘的逆元,用于算组合数
void preWork_facinv() {
inv[100000] = get_inv( fac[100000] , mmod ) ;
for( int i = 99999 ; i >= 0 ; i -- )
inv[i] = 1LL * inv[i+1] * ( i + 1 ) %mmod ;
}
//组合数: n! / m! / (n-m)! = n! * inv[m!] * inv[(n-m)!]
int comb( int n , int m ){
return 1LL * fac[n] * inv[m] %mmod * inv[n-m]%mmod ;
}
//卡特兰公式: C(2n,n-1)/n
int catalan( int x ){
return 1LL * comb( 2 * x , x - 1 ) * get_inv( x , mmod ) %mmod ;
}
//要求模数为质数
long long Lucas( long long n , long long m ) {
if( n < m ) return 0 ;
if( n >= mmod )
return Lucas( n/mmod , m/mmod ) * comb( n%mmod , m%mmod ) ;
else return C[n][m] ;
}
//要求mi两两互质
//http://blog.csdn.net/clove_unique/article/details/54571216
void CRT(){
int cnt , m[100] , c[100] ;
long long M = 1 , ans = 0 ;
scanf( "%d" , &cnt ) ;
for( int i = 1 ; i <= cnt ; i ++ ){
scanf( "%d%d" , &m[i] , &c[i] ) ;
M *= m[i] ;
}
for( int i = 1 ; i <= cnt ; i ++ ){
long long Mi = M / m[i] ;
ans = ( ans + c[i] * Mi %mmod * get_inv( Mi , m[i] ) ) %mmod ;
}
}
int main( int argc , char *argv[] ) {
preWork_C() ;
preWork_fac() ;
preWork_facinv() ;
get_P() ;
return 0 ;
}
#include
#include
#include
#include
using namespace std ;
/*********************
* BSGS
* POJ 2417
* to solve x that fit
* B^x == N ( mod P )
********************/
int mmod , B , N ;
struct hashTable{
int head[7333] , num[100005] , pw[100005] , pre[100005] , tp ;
void init(){
memset( head , 0 , sizeof( head ) ) ;
tp = 0 ;
}
void Insert( int x , int k ){
int id = x%7333 ;
for( int i = head[id] ; i ; i = pre[i] )
if( num[i] == x ) return ;
pre[++tp] = head[id] ;
num[ head[id] = tp ] = x ;
pw[tp] = k ;
}
int Query( int x ){
int id = x%7333 ;
for( int i = head[id] ; i ; i = pre[i] )
if( num[i] == x ) return pw[i] ;
return 0 ;
}
}HT ;
long long s_pow( long long x , long long b ){
long long rt = 1 ;
while( b ){
if( b&1 ) rt = rt * x %mmod ;
x = x * x %mmod ; b >>= 1 ;
}
return rt ;
}
int BSGS(){
if( N == 1 && B != 0 ) return 0 ;
int sqr = ceil( sqrt( mmod ) ) ;
long long now = N , Bsqr = 1 ;
for( int i = 1 ; i <= sqr ; i ++ ){
now = now * B %mmod ; Bsqr = Bsqr * B %mmod ;
if( Bsqr == N ) return i ;
HT.Insert( now , i ) ;
}
now = Bsqr ;
for( int i = 1 ; i <= sqr ; i ++ ){
int tmp = HT.Query( now ) ;
if( tmp ) return i * sqr - tmp ;
now = now * Bsqr %mmod ;
}
return -1 ;
}
int main(){
while( scanf( "%d%d%d" , &mmod , &B , &N ) != EOF ){
HT.init() ;
int tmp = BSGS() ;
if( tmp == -1 ) puts( "no solution" ) ;
else printf( "%d\n" , tmp ) ;
}
}
关于NIM和SG,参见:zyf2000-关于 Nim游戏与SG函数 的一点研究