Codeforces Round #777 D

D. Madoka and the Best School in Russia

我们可以知道x是又其众多因子构成的 所以我们可以先暴力枚举他的因子取出来即可 题解说的不会超过700个 很神秘
然后就是一个因子选和不选 选几次 是不是很像一个背包问题 那我们就可以用dp来解决(先枚举每一个点 在枚举每一种方案)
但是这里我们还要维护合法性 以及顺序问题 状态表示就是dp[i]为从x点到达i点的方案数
我们类似于迭代的做法 只需要每次除的数都必须大于上一次除的数即可 那我们还需要维护一个维度即可
由于x的数据范围较大 我们使用map 来减少空间 并且跳过不需要更新的点
然后就再对于每一个下标做暴力除并且判断其合法性即可

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5+10;
const int M = 998244353;
const int mod = 1000000007;
#define int long long
#define endl '\n'
#define all(x) (x).begin(),(x).end()
#define YES cout<<"YES"<<endl;
#define NO cout<<"NO"<<endl;
#define _ 0
#define INF 0x3f3f3f3f3f3f3f3f
#define fast ios::sync_with_stdio(false);cin.tie(nullptr);
int x,d;
bool check(int n){
    if(n%d==0&&(n%(d*d)))return 1;
    else return 0;
}
void solve() {
    cin>>x>>d;
    vector<int>del;
    map<pair<int,int>,int>dp;
    dp[{x,1}]=1;
    for(int i=1;i<=x;i++){
        if(x%i==0){
            if(check(i))del.push_back(i);
            if(i*i!=x&&check(x/i))del.push_back(x/i);
        }
    }
    int ans=0;
    while(dp.size()){
        auto now=*prev(dp.end());
        int n=now.first.first,k=now.first.second,cot=now.second;
        if(n==1)ans+=cot;
        for(auto i:del){
            if(n%i==0&&i>=k)dp[{n/i,i}]+=cot;
        }
        dp.erase(prev(dp.end()));
    }
    if(ans>=2)YES
    else NO
}
signed main(){
    fast
    int T;cin>>T;
    while(T--) {
        solve();
    }
    return ~~(0^_^0);
}
posted @ 2022-09-13 21:51  ycllz  阅读(22)  评论(0)    收藏  举报