0
点赞
收藏
分享

微信扫一扫

D. Madoka and the Best School in Russia (dp?)

回望这一段人生 2022-03-16 阅读 33

题目link

思路

问题可以理解为:
用 x 的beautiful因子,能否找到不少于2种的方案使得 x = a 1 ∗ a 2 . . ∗ a n x = a_1*a_2..*a_n xa1a2..an 成立,仅顺序不同为一种方案
类似于完全背包求方案数,用 x x x b e a u t i f u l beautiful beautiful 因子为状态进行dp
这里考虑到 x x x 的范围到达 1 e 9 1e9 1e9,用 x x x的因子排序后的下标来映射因子
后面均用的是下标来进行转移;

如何转移呢?
x x x b e a u t i f u l beautiful beautiful因子 i i i作为状态,再枚举x的因子 j j j
当满足 ( x / i % j = = 0 ) (x/i \% j == 0) (x/i%j==0) 时, 用 j j j 转移 i ∗ j i*j ij
这里 ( x / i % j = = 0 ) (x/i \% j == 0) (x/i%j==0) 保证了 i ∗ j i*j ij 也为 x x x 的 因子
存在对应的映射值
详细转移见代码

code

学习于dls

/*
    *@author:bzdhxs
    *@date:2022/03/15
    *@URL:
*/
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<map>
#include<queue>
using namespace std;
template <typename T>
inline void read(T &s){s = 0;T w = 1, ch = getchar();while (!isdigit(ch)) { if (ch == '-') w = -1; ch = getchar(); }while (isdigit(ch))  { s = (s << 1) + (s << 3) + (ch ^48); ch = getchar();} s *= w;}
template <typename T>
inline void write(T s){if (s < 0) putchar('-'), s = -s;if (s > 9) write(s / 10);putchar(s % 10 + '0');}
#define int long long
#define _orz ios::sync_with_stdio(false),cin.tie(0)
#define mem(str,num) memset(str,num,sizeof(str))
#define forr(i,a,b) for(int i = a; i <= b;i++)
#define forn(i,n) for(int i = 0; i < n; i++)
#define dbg() cout <<"0k!"<< endl;
typedef long long ll;
int pri[16] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53};
const int inf = 0x3f3f3f3f;
const int INF = ~0ULL;
const int N = 1e6+10;
int x,d;

bool check(int k){
    return (k % d == 0 && (k/d)%d != 0);
} 

const int M = 100100;
int f[M],id[M],gid[M];

void sol(){
    cin >> x >> d;
    vector<int> fac;
    for(int i = 1;i <= x/i;i++){
        if(x%i == 0){
            fac.push_back(i);
            if(x != i*i) fac.push_back(x/i);
        }
    }
    sort(fac.begin(),fac.end());

	//	 这里是用来映射因子的 考虑到有些值很大内存浪费严重
	//   用两个数组来进行映射 因为最大为1e9 可以使 > 一定值(这里选le5)来分开存 详细见代码
    for(int i = 0; i  < fac.size();i++){
        if(fac[i] <= M) id[fac[i]] = i;
        else gid[x/fac[i]] = i;
    }


    forr(i,0,fac.size()) f[i] = 0;
    f[0] = 1;
    for(int i = 0; i < fac.size();i++)
        if(check(fac[i])){
            for(int j = 0; j < fac.size();j++){
            
            if(x/fac[i] % fac[j] == 0){
                int v = fac[i]*fac[j];
                int d = (v <= M)?id[v]:gid[x/v];
                f[d] = min(f[d]+f[j],2LL);
            
            }
        }
    }
    if(f[fac.size()-1] >= 2 ) puts("YES");
    else puts("NO");
}
signed main()
{

    int t;cin>>t;
    while(t--) sol();
    return 0;
}
举报

相关推荐

0 条评论