UVA 11076(數論 不全相異元素全排列)
阿新 • • 發佈:2018-11-20
題目連結:https://cn.vjudge.net/contest/269773?tdsourcetag=s_pcqq_aiomsg#problem/G
題意:給你N個數,求把他們的全排列加和為多少
參考https://www.cnblogs.com/hbutACMER/p/4235696.html
考慮任意一位i,假設我們在i位放置x,則對應(n−1)!/(d0!∗d1!∗...∗dx!∗...∗d9!)(n−1)!/(d0!∗d1!∗...∗dx!∗...∗d9!)種情況。
PS:前導0也算一種情況,舉個栗子
3
0 0 1
答案是1 1 1
#include<bits/stdc++.h> using namespace std; typedef unsigned long long ull; typedef long long ll; #define rep(i,a,b) for(int i=a;i<=b;i++) #define limit(a,b) memset(a,b,sizeof a) const int N=5e5+7; const int INF = 0x3f3f3f3f; const int mod=1e6; ull f[20]; int b[N],a[N]; // 如何求重複數的全排列 // 元素表述: a1,a1,...a1, a2,a2,...a2,.......,an,an,...an // 其中,a1的個數為N1, a2的個數為N2,以此類推,總個數為M。 // // 則可以證明不重複的排列種類的數目: M!/(N1!*N2!*...*Nn!) //然後這道題就可以轉化成在任意一位i上當前值是a的組合數的情況為s,那麼 //當前位所得的值為a*s,其餘的數字情況一樣處理 int main() { int n; #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); #endif // ONLINE_JUDGE f[0]=1; rep(i,1,12) f[i]=i*f[i-1]; while(scanf("%d",&n)!=EOF,n){ limit(b,0); int cnt=0;// rep(i,1,n) {int t; scanf("%d",&t); b[t]++; if(b[t]==1) a[cnt++]=t; } ull ans=0; ull temp; rep(i,0,cnt-1){//因為每一位的情況是相同的,可以通過模擬發現,因此只需要求一位的情況就好 temp=f[b[a[i]]-1]; //其他位那就相加移位就好。 rep(j,0,cnt-1){ if(i==j) continue; temp*=f[b[a[j]]]; } ans+=(f[n-1]/temp)*a[i]; } temp=ans;//每一位的總和 ans=0; rep(i,0,n-1) ans+=temp,temp*=10; printf("%lld\n",ans); } return 0; }