1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
| #include "iostream" #include "algorithm" #include "cstring" #include "cstdio" #include "cmath" #include "vector" #include "map" #include "set" #include "queue" using namespace std; #define MAXN 500006
#define rep(i, a, b) for (int i = (a), i##end = (b); i <= i##end; ++i) #define per(i, a, b) for (int i = (a), i##end = (b); i >= i##end; --i) #define pii pair<int,int> #define fi first #define se second #define mp make_pair #define pb push_back #define eb emplace_back #define vi vector<int> #define all(x) (x).begin() , (x).end() #define mem( a ) memset( a , 0 , sizeof a ) typedef long long ll; ll n; int m; ll A[MAXN];
struct poi { ll A[9]; poi( ) { mem( A ); } poi( ll a , ll b ) { mem( A ); A[0] = b , A[1] = a; } ll& operator [] ( const int r ) { return A[r]; } poi operator + ( poi x ) { poi S; rep( i , 0 , 8 ) S[i] = A[i] + x[i]; return S; } poi operator - ( poi x ) { poi S; rep( i , 0 , 8 ) S[i] = A[i] - x[i]; return S; } };
int pri[MAXN] , sp[MAXN] , sp2[MAXN] , en; int B; void sieve( ) { B = sqrt( n + 0.5 ); rep( i , 2 , B ) { if( !pri[i] ) pri[++ en] = i , sp[en] = sp[en - 1] + ( i % 3 == 1 ? 1 : i != 3 ? -1 : 0 ) , sp2[en] = sp2[en - 1] + ( i % 3 == 1 ? 1 : 0 ); for( int j = 1 ; j <= en && pri[j] * i <= B ; ++ j ) { pri[i * pri[j]] = 1; if( i % pri[j] == 0 ) break; } } }
int ff( ll x ) { return x % 3 == 1 ? 1 : x % 3 == 2 ? -1 : 0; }
int cc( ll x ) { return ( x % 3 == 1 ? 0 : x % 3 == 2 ? -1 : -1 ); } int A1[MAXN] , A2[MAXN]; int po( ll x ) { return x <= B ? A1[x] : A2[n / x]; } ll g[MAXN] , gp[MAXN]; void getG( ) { int tot = 0; for( ll l = 1 , r ; l <= n ; l = r + 1 ) { r = n / ( n / l ); ++ tot; A[tot] = n / l; if( A[tot] <= B ) A1[A[tot]] = tot; else A2[n / A[tot]] = tot; g[tot] = cc( A[tot] ) , gp[tot] = A[tot] - 1; } rep( i , 1 , en ) for( int j = 1 ; pri[i] * 1ll * pri[i] <= A[j] ; ++ j ) { g[j] = g[j] - ff( pri[i] ) * ( g[po( A[j] / pri[i] )] - sp[i - 1] ); gp[j] = gp[j] - ( gp[po( A[j] / pri[i] )] - ( i - 1 ) ); } }
poi gg( int x ) { return poi( g[x] + gp[x] - 1 >> 1 , gp[x] - g[x] + 1 >> 1 ); }
bool f( int p , int a ) { return ( ( p == 3 && a > 1 ) || ( p % 3 == 1 ) ); }
poi S( ll n , int k ) { if( n <= pri[k] ) return poi(); poi re = ( gg( po( n ) ) - poi( sp2[k] , k - sp2[k] ) ); for( int i = k + 1 ; pri[i] * 1ll * pri[i] <= n && i <= en ; ++ i ) { ll cur = pri[i]; for( int e = 1 ; cur <= n ; ++ e ) { poi pr = S( n / cur , i ) + poi( 0 , e != 1 ); if( f( pri[i] , e ) ) per( k , 8 , 1 ) re[k] = ( re[k] + pr[k - 1] ); else rep( k , 0 , 8 ) re[k] = ( re[k] + pr[k] ); cur *= pri[i]; } } return re; }
void solve() { cin >> n >> m; ++ m; int t = 0; while( m % 3 == 0 ) m /= 3 , ++ t; if( m != 1 ) return void( puts("0") ); sieve( ) , getG( ); cout << S( n , 0 )[t] + ( t == 0 ) << endl; }
signed main() {
solve(); }
|