HDU 4945 2048(dp+快速幂取模)

题目大意:给你一个序列让你求出有多少种组合可以得到2048.结果要对998244353取余。

解题思路:求出不能满足条件的方案数,然后用总的减去不满足的然后乘上其他无关的组合方式,比如3,5这些数字是在构成2048的过程中无用的,所以乘上这些组合出来的情况。

dp[i][j]表示取到第i个2^i的数,其最大的和在j*2^i至(j+1)*2^i-1的方案数。

所以有dp[i][j] += ((dp[i-1][k]+dp[i-1][k+1])*use[i][j-k/2])%mod。表示在i位置时最大和为j的方案数,有一部分是之前已经得到的,一部分是第i次新添加的。

这道题目很卡时间,所以要组合数的取模要用到逆元然后加快速幂取模就可以了啊。

PS:感觉挺好的题目,以后要多做做。

2048

Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)

Total Submission(s): 1052    Accepted Submission(s): 276

Problem Description

Teacher Mai is addicted to game 2048. But finally he finds it‘s too hard to get 2048. So he wants to change the rule:

You are given some numbers. Every time you can choose two numbers of the same value from them and merge these two numbers into their sum. And these two numbers disappear meanwhile.

If we can get 2048 from a set of numbers with this operation, Teacher Mai think this multiset is good.

You have n numbers, A1,...,An. Teacher Mai ask you how many subsequences of A are good.

The number can be very large, just output the number modulo 998244353.

Input

There are multiple test cases, terminated by a line "0".

For each test case, the first line contains an integer n (1<=n<=10^5), the next line contains n integers ai (0<=ai<=2048).

Output

For each test case, output one line "Case #k: ans", where k is the case number counting from 1, ans is the number module 998244353.

Sample Input

4
1024 512 256 256
4
1024 1024 1024 1024
5
1024 512 512 512 1
0

Sample Output

Case #1: 1
Case #2: 11
Case #3: 8

Hint

In the first case, we should choose all the numbers.
In the second case, all the subsequences which contain more than one number are good.

Author

xudyh

Source

2014 Multi-University Training Contest 8

#include <algorithm>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <iomanip>
#include <stdio.h>
#include <string>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <set>
#define eps 1e-10
///#define M 1000100
///#define LL __int64
#define LL long long
///#define INF 0x7ffffff
#define INF 0x3f3f3f3f
#define PI 3.1415926535898
#define zero(x) ((fabs(x)<eps)?0:x)

using namespace std;

const int maxn = 100010;
#define mod 998244353

int num[21];
LL dp[15][2100];
LL use[15][2100];
LL f[maxn];
int n;

int add(int x)
{
    if(x == 0) return 20;
    int ans = 0;
    while(x!=1)
    {
        if(x&1) return 20;
        x >>= 1;
        ans++;
    }
    return ans;
}

LL q_mod(LL a,LL b,LL n)
{
    LL ret=1;
    LL tmp=a%n;
    while(b)
    {
        //基数存在
        if(b&0x1) ret=ret*tmp%n;
        tmp=tmp*tmp%n;
        b>>=1;
    }
    return ret;
}

LL Del(int n, int m)
{
    if(m > n) return 0LL;
    LL ans = f[n];
    ans = (ans*q_mod((f[m]*f[n-m])%mod, mod-2, mod))%mod;
    return ans;
}

void select()
{
    for(int i = 1; i <= 11; i++)
        for(int j = 0; j < 2048; j++) use[i][j] = Del(num[i-1], j);
}

void change()
{
    select();
    for(int i = 0; i < 2048; i++) dp[1][i] = use[1][i];
    for(int i = 2; i <= 11; i++)
    {
        int cnt = (1<<(12-i));
        for(int j = 0; j < cnt; j++)
        {
            for(int k = 0; k <= 2*j+1; k += 2)
            {
                if(!use[i][j-k/2] || !(dp[i-1][k]+dp[i-1][k+1])) continue;
                dp[i][j] += ((dp[i-1][k]+dp[i-1][k+1])*use[i][j-k/2])%mod;
            }
            dp[i][j] %= mod;
        }
    }
    LL ans = 0LL;
    ans = q_mod(2, num[20], mod);
    LL ps = (dp[11][0]+dp[11][1])%mod;
    ps = q_mod(2, n-num[20], mod)-ps;
    ps = (ps+mod)%mod;
    ans = (ans*ps)%mod;
    printf("%I64d\n",ans);
}

void init()
{
    f[0] = 1LL;
    for(LL i = 1; i < maxn; i++) f[i] = (f[i-1]*i)%mod;
}

int main()
{
    int Case = 1;
    init();
    while(~scanf("%d",&n) && n)
    {
        memset(num, 0, sizeof(num));
        memset(dp, 0, sizeof(dp));
        int x;
        for(int i = 0; i < n; i++)
        {
            scanf("%d",&x);
            num[add(x)]++;
        }
        printf("Case #%d: ",Case++);
        change();
    }
    return 0;
}
时间: 2024-10-11 16:48:35

HDU 4945 2048(dp+快速幂取模)的相关文章

hdu 3221 Brute-force Algorithm(快速幂取模,矩阵快速幂求fib)

http://acm.hdu.edu.cn/showproblem.php?pid=3221 一晚上搞出来这么一道题..Mark. 给出这么一个程序,问funny函数调用了多少次. 我们定义数组为所求:f[1] = a,f[2] = b, f[3] = f[2]*f[3]......f[n] = f[n-1]*f[n-2].对应的值表示也可为a^1*b^0%p,a^0*b^1%p,a^1*b^1%p,.....a^fib[n-3]*b^fib[n-2]%p.即a,b的指数从n=3以后与fib数列

HDU - 3003 - Pupu (快速幂取模!)

Pupu Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1133    Accepted Submission(s): 445 Problem Description There is an island called PiLiPaLa.In the island there is a wild animal living in it

hdu 1452 Happy 2004 (快速幂+取模乘法逆元)

Problem Description Consider a positive integer X,and let S be the sum of all positive integer divisors of 2004^X. Your job is to determine S modulo 29 (the rest of the division of S by 29).Take X = 1 for an example. The positive integer divisors of

HDU 5363 Key Set(快速幂取模)

Key Set Problem Description soda has a set $S$ with $n$ integers $\{1, 2, \dots, n\}$. A set is called key set if the sum of integers in the set is an even number. He wants to know how many nonempty subsets of $S$ are key set. Input There are multipl

HDU 5363 Key Set【快速幂取模】

Key Set Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 1886    Accepted Submission(s): 990 Problem Description soda has a set S with n integers {1,2,-,n}. A set is called key set if the sum

HDU 4965 Fast Matrix Calculation (矩阵快速幂取模----矩阵相乘满足结合律)

http://acm.hdu.edu.cn/showproblem.php?pid=4965 利用相乘的可结合性先算B*A,得到6*6的矩阵,利用矩阵快速幂取模即可水过. 1 #include<iostream> 2 #include<stdio.h> 3 #include<iostream> 4 #include<stdio.h> 5 #define N 1010 6 #define M 1010 7 #define K 6 8 using namespa

HDU 4365 正方形格子涂色中心对称轴对称的涂法有多少种-思维-(矩阵坐标关系&amp;快速幂取模)

题意:n*n的格子,涂色,有k种颜料,必须满足旋转任意个90度和翻转之后图片的样子不变,现在已经有m个格子涂过色了,问还有多少种涂法满足上述条件. 分析: 满足上述对称条件,那么涂色的种类问题我们可以放在正方形的一个角来做,因为一个角确定了其他角的颜色也就确定了. 以左上角的下半角为例.共有1+2+....+(n+1)/2个格子,然后记录涂过色的格子对应到这个三角形里的格子数目,用tot来记录,即每输入一个涂过色的格子的坐标我们就在这个三角形里找与之对应的坐标,用vis[][]数组标记是否已经计

HDU - 1097 - A hard puzzle (快速幂取模)

A hard puzzle Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 32633    Accepted Submission(s): 11672 Problem Description lcy gives a hard puzzle to feng5166,lwg,JGShining and Ignatius: gave a a

HDU 5363 元素为1~n的集合有多少个子集的元素和为偶数-思维-(快速幂取模)

题意:一个集合有元素1~n,求他的子集满足这样的条件:子集的所有元素的和是偶数,问有多少个这样的子集 分析: 一个排列组合问题.元素和为偶数,那么奇数肯定要调偶数个,偶数就无所谓了,所以偶数有2^(n/2)种选法,再乘以奇数有(C((n+1)/2,0)+C((n+1)/2,2).....)种选法,再减一,除去空集,注意,上面取奇数的时候用的是(n+1)/2(这里是向下取整的除法),是综合n为偶数和n为奇数两种情况. 组合数性质:C(n,1)+C(n,3)+....=C(n,2)+C(n,4)+.