UVA 11076 Add Again(有重复元素的全排列问题)

UVA 11076 Add Again

题意:

输入N个数字,求这几个数字组成的数之和。
如:1,2,3.组成的数有123,132,213,231,312,321,和为1332.

思路:

有重复元素的全排列类问题:
有k个元素,第 i 个元素 ai ci 个,设总的全排列个数为 x。
那么:设共有 n 个元素(n=ai),得方程

a1!a2!ak!x=n!

得到全排列个数 x ,进而得到每一个数字在每一位出现的次数为 x / n。
例如:
1,2,2每一个数字在每一位出现的次数为 3/3 = 1;
1,2,3每一个数字在每一位出现的次数为 6/3 = 2。

回到求和问题,
<1,2,3>组成的数字有:
123
132
213
231
312
321
sum = (6 * 2)(6 * 2)(6 * 2)
换成十进制即 sum = 12*10^2 + 12 * 10 + 12 = 1332。
综上,
答案的每一位 = 所有数字之和乘以出现次数,
sum=x/naici11..11(n1)

代码:

//#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <algorithm>
#include <functional>
#include <string>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
#include <bitset>

using namespace std;

#define IOS std::ios::sync_with_stdio(false);std::cin.tie(0)
#define clr( x , y ) memset(x,y,sizeof(x))
#define cls( x ) memset(x,0,sizeof(x))
#define pr( x ) cout << #x << " = " << x << endl
#define pri( x ) cout << #x << " = " << x << " "
#define test( t ) int t ; cin >> t ; int kase = 1 ; while( t-- )
#define out( kase ) printf( "Case %d: " , kase++ )
#define mp make_pair
#define pii pair<int,int>
#define pli pair<long long,int>
#define pll pair<long long,long long>
#define fs first
#define se second
#define pb push_back
typedef long long lint;
typedef long long ll;
typedef long long LL;
typedef unsigned long long ULL;
const double eps = 1e-8 ;
const int inf = 0x3f3f3f3f ;
const long long INF = 0x3f3f3f3f3f3f3f3fLL ;

// const int N = ;
int num[20] , a[20] ;
lint fac[20] ;
lint basic[] = { 1 , 11 , 111 , 1111 , 11111 , 111111 , 1111111 , 11111111 , 111111111 ,1111111111 ,11111111111 , 111111111111 } ;
int n ;
void init()
{
    fac[0] = 1 ;
    for ( int i = 1 ; i < 20 ; i++ )
        fac[i] = fac[i-1] * i ;

}
void work()
{
    lint ans = 0 ;
    cls( num ) ;
    for ( int i = 0 ; i < n ; i++ ) {
        scanf( "%d" , a + i ) ;
        ans += a[i] ;
        num[a[i]] ++ ;
    }
    lint x = fac[n] ;
    for (int i = 0; i < 10 ; i++) {
        x /= fac[num[i]] ;
    }
    ans = ans * x * basic[n-1] / n ;
    cout << ans << endl ;
}
int main()
{
    // freopen("my.in","r",stdin);
    // freopen("my.out","w",stdout);
    init() ;
    while( cin >> n && n ) {
        work() ;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值