URAL 1036(dp+高精度)

Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u

Submit Status Practice URAL 1036

Description

You are given a number 1 ≤ N ≤ 50. Every ticket has its 2 N-digit number. We call a ticket lucky, if the sum of its first N digits is equal to the sum of its last N digits. You are also given the sum of ALL digits in the number. Your task is to count an amount of lucky numbers, having the specified sum of ALL digits.

Input

Two space-separated numbers: N and S. Here S is the sum of all digits. Assume that 0 ≤ S ≤ 1000.

Output

The amount of lucky tickets.

Sample Input

input output
2 2
4

Hint

The tickets are 0101, 0110, 1001, 1010 in the example above

求前N位与后N位各个位和相等且总和等于S的2N位数的个数。

注意:每个位上的数字是0-9也就是十进制

状态转移方程:dp[i][j]=sum(dp[i-1][j-k],0<=k<=9)。可想而知最后的数一定会很大。所有操作都用高精度来做

#include<stdio.h>
#include<cstring>
#include<iostream>
using namespace std;
int dp[55][505][105];//第100位存的是数据的长度
int n,tot;
void add(int sum[],int num[])
{
    int i,j,temp[105];
    int len1=sum[100],len2=num[100];
    int max=len1>len2 ? len1:len2;
    int jin=0;
    for(i=0;i<max;i++){
        int m=jin+sum[i]+num[i];
        if(m>=10) {jin=1;m-=10;}
        else jin=0;
        temp[i]=m;
    }
    if(jin) temp[i++]=jin;
    for(j=0;j<i;j++)
        sum[j]=temp[j];
    sum[100]=i;
}
void muti_dan(int num[],int data[],int n,int h)
{
    int temp[105],i,j;
    memset(temp,0,sizeof(temp));
    int len=num[100];
    int jin=0;
    for(i=0;i<len;i++){
        int m=num[i]*n+jin;
        jin=m/10;
        if(jin)m-=jin*10;
        temp[i]=m;
    }
    if(jin) temp[i++]=jin;
    data[100-h]=i;
    for(j=0;j<i;j++){
        data[j]=temp[j];
    }
}
void  multi(int num[],int num1[])
{
    int temp[105],sum[105],i,j;
    memset(sum,0,sizeof(sum));
    int len1=num[100],len2=num1[100];
    for(j=0;j<len2;j++){
        memset(temp,0,sizeof(temp));
        muti_dan(num,&temp[j],num1[j],j);
        temp[100]+=j;
        add(sum,temp);
    }
    for(i=0;i<sum[100];i++){
        num[i]=sum[i];
    }
    num[100]=sum[100];
}
void display(int num[])
{
    int len=num[100];
    for(int i=len-1;i>0;i--)
        cout<<num[i];
    cout<<num[0]<<endl;
}
void solve()
{
    int i,j,k;
    if(tot%2) {printf("0\n");return;}
    int sum=tot/2;
    memset(dp,0,sizeof(dp));
    for(i=0;i<10;i++) {
        dp[0][i][0]=1;
        dp[0][i][100]=1;
    }

    for(i=0;i<n-1;i++){
        for(j=0;j<=sum;j++){
            for(k=0;k<=9&&j+k<=sum;k++){
                add(dp[i+1][j+k],dp[i][j]);
            }
        }
    }

    multi(dp[n-1][sum],dp[n-1][sum]);
    display(dp[n-1][sum]);
}
int main(void)
{
    while(cin>>n>>tot){
        solve();
    }
    return 0;
}

URAL 1036(dp+高精度)

时间: 2024-10-10 10:31:58

URAL 1036(dp+高精度)的相关文章

Lucky Tickets URAL - 1036 dp+大数

用b[i][j]表示递推到第i位时数字和为j的方案数,那么总方案数就是b[n][s/2]的平方 1 n, s = input().split(' ') 2 3 n = int(n) 4 s = int(s) 5 6 if s % 2 == 1: 7 print(0) 8 else: 9 s = int(s // 2) 10 b = [[]] 11 a = [] 12 for i in range(0, 10): 13 a.append(1) 14 for i in range(10, s + 1

DP+高精度 URAL 1036 Lucky Tickets

题目传送门 1 /* 2 题意:转换就是求n位数字,总和为s/2的方案数 3 DP+高精度:状态转移方程:dp[cur^1][k+j] = dp[cur^1][k+j] + dp[cur][k]; 4 高精度直接拿JayYe的:) 5 异或运算的规则: 6 0⊕0=0,0⊕1=1 7 1⊕0=1,1⊕1=0 8 口诀:相同取0,相异取1 9 */ 10 #include <cstdio> 11 #include <cstring> 12 #include <string>

poj 1625 Censored!(AC自动机+DP+高精度)

题目链接:poj 1625 Censored! 题目大意:给定N,M,K,然后给定一个N字符的字符集和,现在要用这些字符组成一个长度为M的字符串,要求不包 括K个子字符串. 解题思路:AC自动机+DP+高精度.这题恶心的要死,给定的不能匹配字符串里面有负数的字符情况,也算是涨姿势 了,对应每个字符固定偏移128单位. #include <cstdio> #include <cstring> #include <queue> #include <vector>

【bzoj2764】[JLOI2011]基因补全 dp+高精度

题目描述 在生物课中我们学过,碱基组成了DNA(脱氧核糖核酸),他们分别可以用大写字母A,C,T,G表示,其中A总与T配对,C总与G配对.两个碱基序列能相互匹配,当且仅当它们等长,并且任意相同位置的碱基都是能相互配对的.例如ACGTC能且仅能与TGCAG配对.一个相对短的碱基序列能通过往该序列中任意位置补足碱基来与一个相对长的碱基序列配对.补全碱基的位置.数量不同,都将视为不同的补全方案.现在有两串碱基序列S和T,分别有n和m个碱基(n>=m),问一共有多少种补全方案. 输入 数据包括三行. 第

bzoj 1089 [SCOI2003]严格n元树(DP+高精度)

1089: [SCOI2003]严格n元树 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 1250  Solved: 621[Submit][Status][Discuss] Description 如果一棵树的所有非叶节点都恰好有n个儿子,那么我们称它为严格n元树.如果该树中最底层的节点深度为d(根的深度为0),那么我们称它为一棵深度为d的严格n元树.例如,深度为2的严格2元树有三个,如下图: 给出n, d,编程数出深度为d的n元树数目. Inp

UVA 10497 - Sweet Child Makes Trouble(DP+高精度)

题目链接:10497 - Sweet Child Makes Trouble 题意:n个物品,原来物品属于一个地方,现在要把物品重新放回去,问能放几种使得每个物品都与原来位置不同 思路:递推,一开始随便搞了个二维状态,dp[i][j]表示i个物品,有j个位置不同,那么dp[n][n]就是答案,递推式为: dp[i][j] = 1 (j == 0) dp[i][j] = (j - 1) * dp[i - 1][j - 1] + dp[i - 1][j] + (i - j + 1) * dp[i -

UVA 12105 - Bigger is Better(DP+高精度)

题目链接:12105 - Bigger is Better 题意:一些火柴,问你能组成整除m最大的数字是多少. 思路:dp[i][j]表示用i根火柴,组成%m余数为j的最大数字,末尾多一个数字k的状态就是dp[i + num[k]][(j * 10 + k) % m],由于最多可能50位数,所以要用高精度. 注意一个优化点,由于高精度的计算上只需要乘10+k,常规的高精度乘法复杂度还是有点高会超时,所以用数组去模拟,每次*10 + k的时候就往后多一位即可. 代码: #include <stdi

1166 矩阵取数游戏[区间dp+高精度]

1166 矩阵取数游戏 2007年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description [问题描述]帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m 的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下:1. 每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素:2. 每次取走的各个元素只能是该元素所在行的行首或行尾:3. 每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分

uva 10497 - Sweet Child Makes Trouble(dp+高精度)

题目链接:uva 10497 - Sweet Child Makes Trouble 题目大意:有个小屁孩很淘气,总是趁父母不在家的时候去拿家具玩,每次拿n个家具玩,但是放回去的时候一定不会将某个物品放回原处,一定要打乱.问说有多少放的方式满足. 解题思路:dp[i]表示说i个数打乱的情况,dp[i]=(dp[i?1]+dp[i?2])?(i?1)每次新增一个数,放在序列的最后一个位置,它的位置一定是正确的,所以一定要和前面i?1个的其中一个交换位置才可以,那么如果选中位置上的物品为错误归放的,