1. 程式人生 > 實用技巧 >b_51_選數字(2*map記錄前後狀態+揹包)

b_51_選數字(2*map記錄前後狀態+揹包)

我們想找出,a中有多少子序列滿足:把當前子序列裡面的所有元素乘起來恰好等於K(1<=n<=1000,2<=K<=100000000)

思路:見程式碼+註釋

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
int main() {
    std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int t; cin>>t;
    while (t--) {
        ll n,k; cin>>n>>k;
        unordered_map<ll, ll> f,g; //f[i]記錄有多少個子序列的乘積為i,g記錄f的上一個狀態
        for (int i=0; i<n; i++) {
            ll x; cin>>x;
            if (k%x) continue;
            g=f, f[x]++;
            for (auto it=g.begin(); it!=g.end(); it++) { //從g中找是k的倍數的x*y,假如y*x是k的倍數,則代表x*y又多了c個可以組成x*y的數
                int y=it->first, c=it->second;
                if (k%(x*y)==0)
                    f[x*y]=(f[x*y]+c)%mod; 
            }   
        }
        cout<<f[k]<<'\n';
    }
    return 0;
}