1. 程式人生 > 其它 >D. Madoka and the Best School in Russia

D. Madoka and the Best School in Russia

D. Madoka and the Best School in Russia
好數的定義是:是d的倍數。
美麗的數的定義是:是好數且不能表示成兩個好數的乘積。
問:給定一個好數x和d,問x是否有超過兩種方式,能夠表示成若干個的美麗的數的乘積(兩個以上)。只回答是與否即可。
根據美麗的數的定義:我們可以假定a是一個美麗的數,則有a=md,且m不是d的倍數。即a是d的倍數,但不是\(d^2\)的倍數。
將x分解成若干個美麗的數的乘積,可以認為\(x=x_1,x_2,x_3,x_4...\),其中\(x_1,x_2,x_3...\)都是d的倍數,但不是\(d^2\)的倍數。
既然這樣,我們可以用DP解決。設f[n]表示當前數除以某些合法的數後到達n的方案數.最後判斷f[1]的方案數與2的關係即可。注意列舉的時候我們要單調的列舉因子.
這個時候就可以跑一下合法的數量的因子的個數,反正很少就對了。

點選檢視程式碼
#include<bits/stdc++.h>
using namespace std;
int T,x,d,b[100000];
map<pair<int,int>,int>mp;
inline bool check(int x)
{
    if(x%d==0&&(x/d)%d!=0) return 1;
    return 0; 
}
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&x,&d);
        int num=0;
        for(int i=1;i<=sqrt(x);++i)
        {
            if(x%i==0)
            {
                if(check(i)) b[++num]=i;
                if(i*i!=x&&check(x/i)) b[++num]=x/i;
            }
        }
        sort(b+1,b+num+1);
        mp.clear();
        mp[{x,num}]=1;
        int ans=0;
        while(mp.size())
        {
            auto now=*prev(mp.end());
            int v=now.first.first,id=now.first.second,cos=now.second;
            if(v==1) ans+=cos;
            for(int i=id;i>=1;--i)
            {
                if(v%b[i]==0)
                {
                    mp[{v/b[i],i}]+=cos;
                }
            }
            mp.erase(prev(mp.end()));
        }
        if(ans>1) puts("YES");
        else puts("NO");
    }
    return 0;
}