题解—简单的玄学
考场上推出来式子之后为了想怎么约分花了很长时间。
其实真的是,时间一长就误入歧途了。
看到取模之后的分数不唯一的那一刻心态很崩。
因为只想到了一个分数约不约分取模之后是相同的,没想到有很多分数都可以取出来这个值。
想了半天如何优化取模的操作,最后搞了一个自己感觉还行的方法。
然后暴\(0\)了。
如何保持心态也是一个问题,其实看到分数不唯一,还是半个小时,要是仔细思考,拿回来\(70pts\)也不是问题。
还有就是真的不要死磕一个方法了,真的不要了。
题解约分的方法
首先先证明一个东西。
对于\(1<a<=2^n\),\(a\)中\(2\)的个数和\(2^n-a\)里面一样
很显然,因为\(2^n\)里面的\(2\)比\(a\)里面多,所以肯定不会影响\(a\)提取出来\(2\)。
当\(m\)小于模数的时候,直接暴力扫一遍分子,然后约掉所有的\(2\),同时记录一下,约掉分母的\(2\)。
只要用那个东西把数转化成可表示的就行了,因为那些数在取模意义下是等效的。
注意一下\(n*m\)过大会爆,所以我先算出来快速幂,在乘逆元。
如果\(m\)大于模数,直接\(log\)求解一个阶乘里面有多少个\(2\),和分母约掉就行了。
具体方法是\(\sum N/i\),\(i\)每次乘\(2\),因为我们要看这一段数中有多少个\(2\)的倍数,然后他们会对答案贡献\(1\)
有多少个\(4\)的倍数,因为他们会对答案额外贡献\(1\)
以此类推,一直乘,直到\(i\)大于\(m\)为止
因为分子有连续的一段长于\(m\)的整数,所以必定是\(0\)。
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#define R register int
#define int long long
#define scanf Ruusupuu = scanf
#define printf Ruusupuu = printf
int Ruusupuu ;
using namespace std ;
typedef long long L ;
typedef long double D ;
typedef pair< int , int > PI ;
const int N = 1e5 + 10 ;
const int M = 1e6 + 3 ;
const int P = 166667 + 10 ;
inline int read(){
int w = 0 ; bool fg = 0 ; char ch = getchar() ;
while( ch < '0' || ch > '9' ) fg |= ( ch == '-' ) , ch = getchar() ;
while( ch >= '0' && ch <= '9' ) w = ( w << 1 ) + ( w << 3 ) + ( ch - '0' ) , ch = getchar() ;
return fg ? -w : w ;
}
inline int qpow( int a , int b ){
int ans = 1 ;
b %= ( M - 1 ) ;
while( b ){
if( b & 1 ) ans = ( ans * a ) % M ;
a = ( a * a ) % M , b >>= 1 ;
} return ans ;
}
int n , m , k , kk , cs , fz = 1 , ny ;
void sc(){
n = read() , m = read() , k = qpow( 2 , n ) ;
}
inline int count( int x ){
int ans = 0 , p = x ;
while( x % 2 == 0 ) x /= 2 , ans ++ ;
// printf( "%lld %lld\n" , qpow( ny , ans ) , k - p ) ;
kk = ( ( ( k - p + M ) % M ) * qpow( ny , ans ) ) % M ;
return ans ;
}
void work(){
ny = qpow( 2 , M - 2 ) ;
int t = 0 ;
for( R i = 1 ; i < m ; i ++ ){
t += count( i ) ;
fz = ( fz * kk ) % M ;
} //printf( "%lld\n" , t ) ;
int fm = ( qpow( ny , t ) * qpow( qpow( 2 , n ) , m - 1 ) ) % M ;
fz = ( fm - fz + M ) % M ;
printf( "%lld %lld\n" , fz , fm ) ;
}
void Work(){
int t = 2 , zt = 0 , ny = qpow( 2 , M - 2 ) ;
while( t < m-1 ) { zt += (int)( (m-1) / t ) , t *= 2 ; }
// printf( "%lld %lld %lld\n" , zt , qpow( ny , zt ) , ny ) ;
int x = ( qpow( qpow( 2 , n ) , m - 1 ) * qpow( ny , zt ) ) % M ;
printf( "%lld %lld\n" , x , x ) ;
}
signed main(){
sc() ;
if( m < M ) work() ;
else Work() ;
return 0 ;
}
$The \ light \ has \ betrayed \ me$

浙公网安备 33010602011771号