zoukankan      html  css  js  c++  java
  • CodeChef--Cards, bags and coins

    题目链接

    Yet another game from chef. Chef gives you N cards and M bags. Each of the N cards has an integer written on it. Now chef asks you to close your eyes and choose a subset of them. He then sums the numbers written on chosen cards, takes its absolute value and gives you those many coins. You win the game if you can divide these coins into M bags with each bag having equal share. As a first step to calculate the probability of winning, you would like to know the number of different subsets which will make you win. Note that all the cards are of different color, so even if 2 cards have the same number written on it, they are still considered as different cards.

    Input

    The first line of the input contains an integer T denoting the number of test cases. The description of T test cases follows.
    First line of each test case contains two integers N and QQ denotes the number of queries to be answered. Second line of each test case contains N integers, the numbers written on cards.
    Following Q lines contain an integer M.

    Output

    For each query output the required Answer modulo 1000000009. Answer is the number of subsets that will ensure you win.

    Constraints

    • 1 ≤ T ≤ 3
    • 1 ≤ N ≤ 100000
    • 1 ≤ Q ≤ 30
    • 1 ≤ M ≤ 100
    • -10^9 ≤ Number on card ≤ 10^9

    Example

    Input
    2
    5 1
    1 2 -1 4 5
    9
    5 2
    1 2 3 4 5
    5
    15
    
    Output
    4
    8
    2
    

    Explanation

    Test Case #1, Query #1
    {}, {1,-1}, {1,-1,4,5}, {4,5} are winning subsets. Sums are 0, 0, 9, 9 respectively.

    Test Case #2, Query #1
    {}, {5}, {1,4}, {2,3}, {1,4,5}, {2,3,5}, {1,2,3,4}, {1,2,3,4,5} are winning subsets. Sums are 0, 5, 5, 5, 10, 10, 10, 15 respectively.

    Test Case #2, Query #2
    {}, {1,2,3,4,5} are winning subsets. Sums are 0 and 15 respectively.

    Author's Note

    Time Limit is not very strict (Yes, not very loose either) if correct Algorithm is used.Author's solution passes with 2 sec Time Limit (C++ solution, using scanf and printf).
    Maximum Input File Size < 4MB.

    题意:给出n个数,然后还有一个数字m,问有多少种方法可以从n个数中选出一些数使得这些数的和是m的倍数。

    很好的一道题,学到了很多。首先对于自己的基础之差感动汗颜。

    第一,对C(n, k)的打表。。。这里还是说下自己的想法吧,如果n<10^3,这个数据量基本是可以用递推的,二维数组C[n][k]记录。

    像这题的n<10^5,显然无法开出巨表,所以可以使用C(n, k) = n!/(k! * (n -k)!)..这样就可以通过记录n!和n!的逆来进行求解,

    如果题目给出的模数是个质数,就可以通过费马小定理很方便的求出一个数的逆元,当然扩展gcd也是可以的。

    其次,对于这题的思路,看到题目和数据范围就应该想到实际上真正的数据范围就只有[0, m)...所以每次询问直接将A[i]模m,然后

    得到每个数出现的次数。这样就可以得到dp的基本模型了。

    dp[i][j]表示从0到i这些数中选一些数模m为j的方案数,然后dp[i][j]可以从dp[i-1][0..m-1]得到。

     Accepted Code:

     1 /*************************************************************************
     2     > File Name: ANUCBC.cpp
     3     > Author: Stomach_ache
     4     > Mail: sudaweitong@gmail.com
     5     > Created Time: 2014年09月04日 星期四 14时13分00秒
     6     > Propose: 
     7  ************************************************************************/
     8 #include <cmath>
     9 #include <string>
    10 #include <cstdio>
    11 #include <fstream>
    12 #include <cstring>
    13 #include <iostream>
    14 #include <algorithm>
    15 using namespace std;
    16 /*Let's fight!!!*/
    17 
    18 #define rep(i, n) for (int i = (0); i < (n); i++)
    19 #define FOR(i, a, b) for (int i = (a); i <= (b); i++)
    20 const int MAX_N = 100050;
    21 const int MAX_M = 101;
    22 const int MOD = 1e9 + 9;
    23 typedef long long LL;
    24 LL fact[MAX_N], ifact[MAX_N];
    25 
    26 LL pow_mod(LL a, LL b) {
    27       LL res = 1;
    28     while (b) {
    29           if (b & 1) res = (res * a) % MOD;
    30         a = (a * a) % MOD;
    31         b >>= 1;
    32     }
    33     return res;
    34 }
    35 
    36 //fact and ifact
    37 void init() {
    38       fact[0] = fact[1] = ifact[0] = ifact[1] = 1;
    39     FOR (i, 2, MAX_N - 50) {
    40           fact[i] = (fact[i - 1] * i) % MOD;
    41         ifact[i] = (ifact[i - 1] * pow_mod(i, MOD - 2)) % MOD;
    42     }
    43 }
    44 
    45 int C(int n, int k) {
    46       return (fact[n] * ifact[k] % MOD) * ifact[n - k] % MOD;
    47 }
    48 
    49 int A[MAX_N], cnt[MAX_M];
    50 LL dp[MAX_M][MAX_M], choose[MAX_M][MAX_M];
    51 
    52 int main(void) {
    53     init(); // precomputation 
    54 
    55     ios::sync_with_stdio(false);
    56     int T;
    57     cin >> T;
    58     while (T--) {
    59         int N, Q, M;
    60         cin >> N >> Q;
    61         rep (i, N) cin >> A[i];
    62         while (Q--) {
    63             cin >> M;
    64             memset(cnt, 0, sizeof(cnt));
    65             rep (i, N) cnt[(A[i] % M + M) % M]++;
    66 
    67             memset(choose, 0, sizeof(choose));
    68             rep (i, M) FOR (j, 0, cnt[i]) {
    69                   choose[i][j * i % M] = (choose[i][j * i % M] + C(cnt[i], j)) % MOD;
    70             }
    71 
    72             memset(dp, 0, sizeof(dp));
    73             dp[0][0] = choose[0][0];
    74             FOR (i, 1, M-1) rep (j, M) rep (k, M) dp[i][j] = (dp[i][j] + dp[i - 1][(j - k + M) % M] * choose[i][k]) % MOD;
    75 
    76             cout << dp[M - 1][0] << endl;
    77         }
    78     }
    79     return 0;
    80 }
  • 相关阅读:
    奔跑吧DKY——团队Scrum冲刺阶段-Day 3
    奔跑吧DKY——团队Scrum冲刺阶段-Day 2
    奔跑吧DKY——团队Scrum冲刺阶段博客汇总
    奔跑吧DKY——团队Scrum冲刺阶段-Day 1-领航
    哈夫曼编码的实现
    电子政务作业——我为政府网站纠错
    20172309 2018-2019《程序设计与数据结构》课程总结
    # Do—Now——团队冲刺博客_总结篇
    数据结构之哈夫曼树
    关于在ViewPager的子页面中不能跳转的问题
  • 原文地址:https://www.cnblogs.com/Stomach-ache/p/3956953.html
Copyright © 2011-2022 走看看