• UVALive


    题目链接:

    http://acm.hust.edu.cn/vjudge/problem/47664

    Eleven

    Time Limit: 5000MS
    #### 问题描述 > In this problem, we refer to the digits of a positive integer as the sequence of digits required to write > it in base 10 without leading zeros. For instance, the digits of N = 2090 are of course 2, 0, 9 and 0. > Let N be a positive integer. We call a positive integer M an eleven-multiple-anagram of N if and > only if (1) the digits of M are a permutation of the digits of N, and (2) M is a multiple of 11. You are > required to write a program that given N, calculates the number of its eleven-multiple-anagrams. > As an example, consider again N = 2090. The values that meet the first condition above are 2009, > 2090, 2900, 9002, 9020 and 9200. Among those, only 2090 and 9020 satisfy the second condition, so > the answer for N = 2090 is 2.

    输入

    The input file contains several test cases, each of them as described below.
    A single line that contains an integer N (1 ≤ N ≤ 10100).

    输出

    For each test case, output a line with an integer representing the number of eleven-multiple-anagrams
    of N . Because this number can be very large, you are required to output the remainder of dividing it
    by 109 + 7.

    样例

    sample input
    2090
    16510
    201400000000000000000000000000

    sample output
    2
    12
    0

    题意

    给你一串数,求由这些数排列组合成的能被11整除的数的个数。

    题解

    能被11整除的数有一个特点,(偶数位的和-奇数位的和)%11=0;
    dp[i][j][k] (0<=i-1<=9) 表示统计到i-1的时候,偶数位已经有j个数时,(y-x)%11==k(y代表偶数位和,x代表奇数位和)的情况数。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    
    typedef long long LL;
    
    const int maxn = 111;
    const int maxm = 15;
    const int mod = 1e9 + 7;
    char str[maxn];
    int cntv[maxm];
    int n;
    LL C[maxn][maxn];
    
    LL dp[maxm][maxn][maxm];
    LL solve(int n) {
    	memset(dp, 0, sizeof(dp));
    	dp[0][0][0] = 1;
    	int sum = 0,need=n/2;
    	for (int i = 1; i <= 10; i++) {
    		for (int j = 0; j <= sum&&j <= need; j++) {
    			for (int dj = 0; dj <= cntv[i - 1] && (j + dj) <= need; dj++) {
    				int dx = (dj - (cntv[i - 1] - dj))*(i-1)%11;
    				dx = (dx%11 + 11) % 11;
    				for (int k = 0; k < 11; k++) {
    					int nk = (k + dx) % 11;
    					dp[i][j + dj][nk] = (dp[i][j + dj][nk]+dp[i - 1][j][k]*C[need-j][dj]%mod*C[n-need-(sum-j)][cntv[i-1]-dj]%mod)%mod;
    				}
    			}
    		}
    		sum += cntv[i - 1];
    	}
    	return dp[10][need][0];
    }
    
    void pre() {
    	memset(C, 0, sizeof(C));
    	C[0][0] = 1;
    	for (int i = 1; i < maxn; i++) {
    		C[i][0] = 1;
    		for (int j = 1; j <= i; j++) {
    			C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % mod;
    		}
    	}
    }
    
    void init() {
    	memset(cntv, 0, sizeof(cntv));
    }
    
    int main() {
    	pre();
    	while (scanf("%s", str) == 1) {
    		init();
    		n = strlen(str);
    		for (int i = 0; i < n; i++) {
    			cntv[str[i] - '0']++;
    		}
    		LL ans = solve(n);
    		if (cntv[0]) {
    			//扣掉第一位为0的情况
    			cntv[0]--;
    			ans -= solve(n - 1);
    		}
    		ans = (ans%mod + mod) % mod;
    		printf("%lld
    ", ans);
    	}
    	return 0;
    }
    

    Notes

    确定阶段的划分很重要!比如这题,用不同的数字作为阶段性,非常典型。
    往往找到了阶段性,对状态转移方程的设计也会更明确。

  • 相关阅读:
    5.线性回归算法
    4.K均值算法--应用
    3.K均值算法
    机器学习2
    机器学习1
    第十五次作业
    第十三次作业
    第十一次作业
    P1250 种树
    P1516 青蛙的约会
  • 原文地址:https://www.cnblogs.com/fenice/p/5735151.html
Copyright © 2020-2023  润新知