zoukankan      html  css  js  c++  java
  • [CF986F]Oppa Funcan Style Remastered[exgcd+同余最短路]

    题意

    给你 (n)(k) ,问能否用 (k) 的所有 (>1) 的因子凑出 (n) 。多组数据,但保证不同的 (k) 不超过 50 个。

    (nleq 10^{18}, kleq 10^{15})

    分析

    • (k) 的质因子数量为 (m)
    1. 如果 (k=1) 一定不行。

    2. 如果 (m=1) 直接判断是否可以整除。

    3. 如果 (m=2) 就是求 (ax+by=n) 是否存在非负整数解。

      根据 (ax equiv n (mod b)) 可以得到 (xequiv na^{(-1)} (mod b))

      只需要判断最小的 (x*a) 是否 (le n) 即可。

    4. 如果 (mge 3) 一定存在一个最小质因子 (le 10^5) ,此时就可以套用同余最短路来求解了。

      具体地,我们将最小质因子单独拿出来,答案可以写成 (n\%p+kp​) 的形式,当且仅当 (n\%p​) 可以用其他质因子凑出,且他们的和 (le n​) 时才能凑出 (n​) 。利用最短路求解这种转移成环的问题。

    • 主要复杂度在处理质因子,可以记录 (5 imes 10^7) 以内的质因子加快枚举。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    #define go(u) for(int i = head[u], v = e[i].to; i; i=e[i].lst, v=e[i].to)
    #define rep(i, a, b) for(int i = a; i <= b; ++i)
    #define pb push_back
    #define re(x) memset(x, 0, sizeof x)
    inline int gi() {
        int x = 0,f = 1;
        char ch = getchar();
        while(!isdigit(ch)) { if(ch == '-') f = -1; ch = getchar();}
        while(isdigit(ch)) { x = (x << 3) + (x << 1) + ch - 48; ch = getchar();}
        return x * f;
    }
    template <typename T> inline void Max(T &a, T b){if(a < b) a = b;}
    template <typename T> inline void Min(T &a, T b){if(a > b) a = b;}
    const int N = 1e5 + 7;
    const LL inf = 1e18 + 7;
    int T, qc;
    bool vis[N], ans[N];
    LL dis[N];
    struct qs {
    	LL n, k; int id;
    	bool operator <(const qs &rhs) const {
    		return k < rhs.k;
    	}
    }q[N];
    struct data {
    	int u;LL dis;
    	bool operator <(const data &rhs) const {
    		return rhs.dis < dis;
    	}
    };
    priority_queue<data>Q;
    vector<LL> pf;
    void dijk(int n) {
    	for(int i = 0; i < n; ++i) dis[i] = inf;
    	memset(vis, 0, sizeof vis);
    	dis[0] = 0;Q.push((data){ 0, 0});
    	
    	while(!Q.empty()) {
    		int u = Q.top().u;Q.pop();
    		if(vis[u]) continue;vis[u] = 1;
    		for(int i = 1; i < pf.size(); ++i) {
    			int v = (u + pf[i]) % n;
    			if(dis[u] + pf[i] >= 0 && dis[u] + pf[i] < dis[v]) {
    				dis[v] = dis[u] + pf[i];
    				Q.push((data){ v, dis[v]});
    			}
    		}
    	}
    }
    void exgcd(LL a, LL b, LL &x, LL &y) {
    	if(!b) { x = 1, y = 0; return;}
    	exgcd(b, a % b, y, x); y -= x * (a / b);
    }
    const int num_sz = 5e7 + 7;
    int t, pc;
    int pri[num_sz];
    bool visp[num_sz];
    void pre(int n) {
    	int to;
    	for(int i = 2; i <= n; ++i) {
    		if(!visp[i])  pri[++pc] = i;
    		for(int j = 1; (to = i * pri[j]) <= n; ++j) {
    			visp[to] = 1;
    			if(i % pri[j] == 0) break;
    		}
    	}
    }
    int main() {
    	pre(5e7);
    	T = gi();
    	rep(i, 1, T) {
    		LL a, b;
    		scanf("%lld%lld", &a, &b);
    		q[++qc] = (qs){ a, b, i};
    	}
    	sort(q + 1, q + 1 + qc);
    	int cnt = 0;
    	for(int i = 1, j = 1; i <= T; i = j + 1, j = i) {
    		pf.clear();
    		while(j + 1 <= T && q[j + 1].k == q[j].k) ++j;
    		
    		LL x = q[i].k;
    		for(int k = 1, l = (int)sqrt(x); k <= pc && pri[k] <= l; ++k) if(x % pri[k] == 0){
    			while(x % pri[k] == 0) x /= pri[k];
    			pf.pb(pri[k]);
    		}
    		if(x > 1) pf.pb(x);
    		if(pf.empty()) continue;
    		if(pf.size() == 1) {
    			for(int k = i; k <= j; ++k)
    				ans[q[k].id] = q[k].n % q[k].k == 0;
    			continue;
    		}
    		if(pf.size() == 2) {
    			LL x, y, inva;
    			exgcd(pf[0], pf[1], x, y);
    			inva = (x + pf[1]) % pf[1];
    			for(int k = i; k <= j; ++k) 
    				ans[q[k].id] =pf[0] * (q[k].n % pf[1] * inva % pf[1]) <= q[k].n;
    			continue;
    		}
    		sort(pf.begin(), pf.end());
    		dijk(pf[0]);
    		for(int k = i; k <= j; ++k)
    			ans[q[k].id] = dis[q[k].n % pf[0]] <= q[k].n;
    	}
    	for(int i = 1; i <= T; ++i) puts(ans[i] ? "YES": "NO");
    	return 0;
    }
    
    
  • 相关阅读:
    C语言printf语法
    Android动画
    【转】Android内存(内存溢出 内存不足 内存低 .)优化详解
    Android dialog在有的手机上宽度不能充满屏幕的问题
    ios单例模式(Singleton)
    给ImageButton设置按下的效果
    Dynamics CRM Entity Relationship Many to Many (N:N)
    Python实现Mysql数据库连接池
    python获取指定时间差的时间
    Visual studio debug—Process with an Id of 5616 is not running的解决方法
  • 原文地址:https://www.cnblogs.com/yqgAKIOI/p/10177276.html
Copyright © 2011-2022 走看看