由此我们可以求出n?对应的序列。而这个序列的每一种排列都对应一个数。那么答案就是这个序列排列组合的数量。
当然,有两个条件需要满足:
1.由于是余数,所以第?i位上的数小于i+1?。
2.最后一位不能为0?,因为那样在倒数第二位时?n就已经为0?,就会提前结束。
对于第一个条件,我们会发现对于任意?x>y,那么?x能选的位置?y一定能选,但y?能选的位置x?不一定能选。因此我们从大往小挨个计算可行的情况即可。
对于第二个条件,我们只需按照最后一位可以为0?的情况计算结果,再计算最后一位一定是0?的结果(把?0放到最后一位上),两数相减便是答案。
数组开到20就可以了。
是否预处理C?无所谓,反正范围挺水的
#include<bits/stdc++.h> #define int long long using namespace std; int b[100]; int bl; int c[100][100];//j选i个 void init()//预处理C { for(int j=0;j<=20;j++) c[0][j]=1; for(int i=1;i<=20;i++) { for(int j=i;j<=20;j++) { c[i][j]=c[i-1][j-1]+c[i][j-1]; } } } void fen(int x)//x对应的序列 { int k=2; while(x) { b[x%k]++; x/=k; k++; bl++;//bl是序列的总元素数量 } return; } int pin() { int ans=1; int s=0; for(int i=20;i>=0;i--) { if(!b[i]) continue; ans*=c[b[i]][min(bl-i+1,bl)-s];//排列组合 s+=b[i]; } return ans; } signed main() { init(); int T; cin>>T; while(T--) { int n; cin>>n; memset(b,0,sizeof(b)); bl=0; fen(n); int x=pin(); int y=0; if(b[0]) { b[0]--; bl--; y=pin();//最后一位一定是零的情况 } cout<<x-y-1<<endl; } return 0; }
【CF1267K】Key Storage——数论 排列组合 c++
原文:https://www.cnblogs.com/CGY2007/p/14431900.html