1366D - Two Divisors

题意:寻找d1 > 1, d2 > 1,使得d1 | ai, d2 | ai且gcd(d1 + d2, ai) = 1;

暴力理解题意:
处理出d | ai,枚举验证(超时显然)

假设我们已经找到了符合题意得d1和d2,则有一下性质:
1.gcd(d1, d2) = 1;
2.\(\forall\) p \(\mid\) ai, 有 p \(\nmid\) (d1 + d2)

\(\forall\) p \(\mid\) ai, p \(\mid\) d1 与 p \(\mid\) d2 只能其中一个成立
则有:

  1. \(\forall\) p \(\mid\) ai 且 p \(\mid\) d1 且 p \(\nmid\) d2, 有 d1 + d2 = d2 (mod p)
  2. \(\forall\) p \(\mid\) ai 且 p \(\nmid\) d1 且 p \(\mid\) d2, 有 d1 + d2 = d1 (mod p)

所以根据上述分析,我们可以得出最易求解的答案:
将ai所有质因子分成两部分,一部分分给d1, 一部分分给d2;
更进一步:
d1为ai的最小质因子,d2为ai除于d1的幂剩余的存在

到此,题目完美解决:
我们从目标出发,假设我们已经求解出答案,得出答案下的某些重要特性,并依据这些特性不断简化,得到核心特征,即答案符合该核心特征,
然后构造出符合这种核心特征的合理解,证明符合该核心特征的解均符合目标。
简化:从终点出发,得出终点的核心特征,证明终点与核心特征之间是充要关系。然后依据核心特征构造合理解。

点击查看代码
#include<bits/stdc++.h>

using i64 = long long;

int main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int n; std::cin >> n;

    std::vector<int> a(n);
    for(int i = 0; i < n; ++i){
        std::cin >> a[i];
    }

    std::vector<int> vis(10000001), pf(10000001), p;
    for(int i = 2; i <= 10000000; ++i){
        if(!vis[i]){
            p.push_back(i);
            pf[i] = i;
        }
        for(int j = 0; j < (int)p.size() && i * p[j] <= 10000000; ++j){
            vis[i * p[j]] = 1;
            pf[i * p[j]] = p[j];
            if(i % p[j] == 0){
                break;
            }
        }
    }

    std::vector<int> ans1(n, -1), ans2(n, -1);
    for(int i = 0; i < n; ++i){
        int now = a[i];
        while(now % pf[a[i]] == 0){
            now /= pf[a[i]];
        }
        if(now != 1){
            ans1[i] = pf[a[i]], ans2[i] = now;
        }
    }

    for(auto x : ans1){
        std::cout << x << ' ';
    }   std::cout << '\n';
    for(auto x : ans2){
        std::cout << x << ' ';
    }   std::cout << '\n';
    
    return 0;
}
posted on 2022-09-14 15:04  航海士  阅读(33)  评论(0)    收藏  举报