CF986F

CF986F [* easy]

不难注意到只需要保留 \(k\) 的质因子。

然后问题变成 \(n\) 能否用 \(k\) 的质因子表示。

设最小的质因子为 \(d\),显然可以在模 \(d\) 意义跑最短路解方程,复杂度 \(\mathcal O(dk\log)\)

如果约数个数仅为 \(2\) 只需要考虑方程 \(ax+by=n\) 是否存在正整数解,可以 exgcd 算一算。

否则复杂度显然是 \(k^{\frac{1}{3}}\) 级别的。

总复杂度 \(\mathcal O(50k^{\frac{1}{3}}d\log k+T\log n)\),如果不写 PR 就是 \(\mathcal O(50k^{\frac{1}{3}}d\log k+T\log n+\frac{50k^{\frac{1}{2}}}{\ln k})\)

这里采用暴力分解质因子。

\(Coed:\)

#include<bits/stdc++.h>
using namespace std ;
#define Next( i, x ) for( register int i = head[x]; i; i = e[i].next )
#define rep( i, s, t ) for( register int i = (s); i <= (t); ++ i )
#define drep( i, s, t ) for( register int i = (t); i >= (s); -- i )
#define re register
#define int long long
int gi() {
	char cc = getchar() ; int cn = 0, flus = 1 ;
	while( cc < '0' || cc > '9' ) {  if( cc == '-' ) flus = - flus ; cc = getchar() ; }
	while( cc >= '0' && cc <= '9' )  cn = cn * 10 + cc - '0', cc = getchar() ;
	return cn * flus ;
}
const int inf = 1e15 + 7 ; 
const int N = 3.5e7 + 5 ; 
const int M = 1e5 + 5 ; 
const int K = 15 ; 
int n, m, tk, ans[M], st[K], dis[M] ;
int vis[M], num, top, p[N / 10] ; 
bool isp[N] ; 
struct node {
	int id, w, k ; 
} Q[M] ; 
bool cmp(node x, node y) { return x.k < y.k ; }
void init(int x) {
	for(re int i = 2; i <= x; ++ i) {
		if(!isp[i]) p[++ top] = i ;
		for(re int j = 1; j <= top && p[j] * i <= x; ++ j) {
			isp[i * p[j]] = 1 ; 
			if(i % p[j] == 0) break ; 
		}
	}
}
void Make(int x) {
	num = 0 ;
	for(re int i = 1; i <= top && p[i] <= sqrt(x); ++ i) {
		if( x % p[i] ) continue ; 
		while( x % p[i] == 0 ) x /= p[i] ; 
		st[++ num] = p[i] ; 
	}
	if( x != 1 ) st[++ num] = x ;  
}
queue<int> q ; 
void SPFA() {
	rep( i, 0, st[1] ) dis[i] = inf, vis[i] = 0 ; 
	dis[0] = 0, q.push(0) ; 
	while(!q.empty()) {
		int u = q.front() ; q.pop(), vis[u] = 0 ;
		rep( i, 2, num ) {
			int v = (u + st[i]) % st[1] ; 
			if( dis[v] > dis[u] + st[i] ) {
				dis[v] = dis[u] + st[i] ;
				if(!vis[v]) vis[v] = 1, q.push(v) ; 
			}
		}
	}
} 
void Dij() {
	sort( st + 1, st + num + 1 ), SPFA() ; 
}
void exgcd(int a, int b, int &x, int &y) {
	if(!b) { x = 1, y = 0 ; return ; }
	exgcd(b, a % b, y, x), y -= (a / b) * x;
}
int get(int v, int a, int b) {
	int x, y ; exgcd(a, b, x, y);
	x = ((v % b) * x % b + b) % b;
	return (v - x * a >= 0) ;
}
signed main()
{
	m = gi() ; init(N - 5) ;
	rep( i, 1, m ) Q[i].id = i, Q[i].w = gi(), Q[i].k = gi() ; 
	sort(Q + 1, Q + m + 1, cmp) ; 
	for(re int l = 1, r; l <= m; l = r) {
		r = l, Make(Q[l].k) ; 
		if( num >= 3 ) Dij() ; 
		while( Q[r].k == Q[l].k ) {
			if( num >= 3 ) ans[Q[r].id] = (Q[r].w >= dis[Q[r].w % st[1]]) ;
			if( num == 1 ) ans[Q[r].id] = ((Q[r].w % st[1]) == 0) ; 
			if( num == 2 ) ans[Q[r].id] = get(Q[r].w, st[1], st[2]) ;
			if( Q[r].k == 1 ) ans[Q[r].id] = 0 ; 
			++ r ; 
		}
	}
	rep( i, 1, m ) (ans[i]) ? puts("YES") : puts("NO") ; 
	return 0 ;
}
posted @ 2020-10-20 19:30  Soulist  阅读(140)  评论(0编辑  收藏  举报