组合数学+神坑——cf1267K

/*
首先求出multiset,设其大小是size,那么除数集合是[2,size+1]
对于multiset里面的某个余数x,其可能的除数集合就是[x+1,size+1]
将余数从大到小统计贡献
本题有一个坑:最后个余数的位置里不能填0,因为余数是0表示被除尽,那么商必不可能是0,所以其不可能是最后一个余数
    所有最后一位填0的情况要减去
答案要-1
*/
#include<bits/stdc++.h>
using namespace std;
#define ll long long 

ll k,C[21][21];
vector<ll>a; 
void init(){
    C[0][0]=1;
    for(int i=1;i<=20;i++){
        C[i][0]=1;
        for(int j=1;j<=i;j++)
            C[i][j]=C[i-1][j]+C[i-1][j-1]; 
    }
}

ll solve(){
    ll res=1;
    int len=0,tot=0;
    for(int i=a.size()-1;i>=0;i--){
        if(i==0){
            len++;
            if(a[i]<2)
                res*=C[a.size()-tot][len];
            else res=0;
        }
        else {
            ++len;
            if(a[i]==a[i-1])continue;
            res*=C[(a.size()+1-a[i])-tot][len];
            tot+=len;
            len=0;
        }
    }
    return res;
}

int main(){
    int t;cin>>t;
    init();
    while(t--){
        a.clear();
        cin>>k;
        int x=2;
        while(k){
            a.push_back(k%x);
            k/=x;x++;
        }
        sort(a.begin(),a.end());
        ll ans=solve();
        //减去0是最后一个余数的情况 
        if(a[0]==0){
            a.erase(a.begin());ans-=solve();
        }
        cout<<ans-1<<'\n'; 
    }
} 

猜你喜欢

转载自www.cnblogs.com/zsben991126/p/12285360.html