「hdu6682」Rikka with Mista【基数排序+单调优化】

Rikka with Mista

Time Limit: 12000/6000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 522 Accepted Submission(s): 135

Problem Description

R i k k a Rikka Rikka is a fervent fan of J o J o ′ s JoJo's JoJos Bizarre Adventure. As the last episode of Golden Wind has been aired, R i k k a Rikka Rikka, with the help of Y u t a Yuta Yuta, sets up this problem to express the love to M i s t a Mista Mista.

M i s t a ′ s Mista's Mistas lucky number is 4. Today, M i s t a Mista Mista wants to test his luck with n magic cards: For each card, there is a non-negative integer on each side. The two numbers on the i − t h i-th ith card are w i w_i wi and 0 0 0.

Firstly, M i s t a Mista Mista puts these n n n cards to table one by one. For each card, the probability of the w i w_i wi side to be upward is 12 12 12, and these probabilities are independent with each other. As a result, there are n n n integers on the table. Mista then sums up all these integers and counts the number of 4 s 4s 4s in the decimal representation of this sum: He uses this result to measure his luckiness.

Since it’s possible for each side of each card to be upward, there are 2 n 2^n 2n possible states in total. You are required to calculate the sum of the results for all these situations.

Input

The first line of the input contains a single integer T ( 4 ≤ T ≤ 4 ) T(4\leq T\leq 4) T(4T4), the number of test cases.

For each test case, the first line contains a single integer n ( 4 ≤ n ≤ 40 ) n(4\leq n\leq 40) n(4n40), the number of the cards.

The second line contains n n n integers w 1 , … , w n ( 4 ≤ w i ≤ 44444444 ) w_1,…,w_n(4\leq w_i\leq 44444444) w1,,wn(4wi44444444), the positive numbers on the cards.

Output

For each test case, output a single line with a single integer, the answer.

Hint

There are 44 4s in the sample input. Mista would like this sample input.

In the first test case, there is 1 state with the sum equal to 0; 4 states with the sum equal to 4; 6 states with the sum equal to 8; 4 states with the sum equal to 12 and 1 state with the sum equal to 16.

Therefore, there are only 4 situations with the result equal to 1 while on other cases, the result is 0. So the answer should be 4.

Sample Input

4
4
4 4 4 4
4
4 4 44 44
4
4 44 44 4444
4
444 44444 44444 4444444

Sample Output

4
10
24
38

Source

2019 Multi-University Training Contest 9

题意

  • 就是给你 n n n个数,每个数可选可不选,所以一共有 2 n 2^n 2n的方案,设第 i i i个方案中所有数字的和 k k k的数位中 4 4 4的出现次数为 c n t i cnt_i cnti,求
    ∑ i = 1 2 n c n t i \sum_{i=1}^{2^n}{cnt_i} i=12ncnti

题解

  • 首先很容易想到的无脑做法是先 m e e t   i n   m i d d l e meet\ in\ middle meet in middle将所有数分成两半分别暴力算出所有可能的 s u m l , s u m r sum_l,sum_r suml,sumr,然后考虑每一位算贡献,比如算第 i i i位时,先把所有的 s u m l sum_l suml s u m r sum_r sumr模上 1 0 i + 1 10^{i+1} 10i+1然后枚举 s u m l sum_l suml,在 s u m r sum_r sumr中找出区间 [ 4 × 1 0 i − s u m l , 5 ∗ 1 0 i − s u m l ) [4\times 10^i-suml,5*10^i-suml) [4×10isuml,510isuml)内的数量加到 a n s ans ans里,还需要找出区间 [ 1 0 i + 1 + 4 × 1 0 i − s u m l , 1 0 i + 1 + 5 × 1 0 i − s u m l ) [10^{i+1}+4\times 10^i-suml,10^{i+1}+5\times10^i-suml) [10i+1+4×10isuml,10i+1+5×10isuml),这里酸的是进位后产生的 4 4 4,比如 7 + 7 7+7 7+7,对于找区间内的数,可能需要排序然后 l o w e r _ b o u n d lower\_bound lower_bound,所以时间复杂度 O ( T ∗ 10 ∗ 2 n 2 ∗ n 2 ) O(T*10*2^{\frac{n}{2}}*\frac{n}{2}) O(T1022n2n),而且常数巨大。。显然就炸了
  • 容易想到 4 4 4的产生要么是加上进位后产生要么就是无低位进位相加产生,那么分类计算,对于每一个 s u m l sum_l suml,假设 s u m l , s u m r sum_l,sum_r suml,sumr是按照最低的 i i i位排好序,那么显然在统计的时候枚举 s u m l sum_l suml的话,可行的 s u m r sum_r sumr p o s pos pos是单调的,所以就可以 O ( 2 n ) O(2^n) O(2n)找出所有答案,对于按照最低的 i i i位排序,实际上就是从低位开始的基数排序过程
  • 算法复杂度 O ( T × n × 2 n ) O(T\times n\times 2^n) O(T×n×2n)

代码

#pragma GCC optimize ("Ofast")
#include<bits/stdc++.h>

using namespace std;
const int maxn=2e6+10;
struct node{
    long long l,r;
};
vector<node> a,b,c[10],d[10];
int n,val[maxn];

void solve(int *a,int k,vector<node>&b)
{
    for(int i=0;i<(1<<k);i++) {
        long long s=0;
        for(int j=0;j<k;j++) if(i&(1<<j)) s+=a[j];
        b.push_back(node{s,0});
    }
}

long long get_jin0(vector<node>&a,vector<node>&b,long long base) //处理没有进位的答案
{
    int point=b.size()-1;long long ans=0;
    for(int i=0;i<a.size();i++) {
        while(point>=0&&a[i].r+b[point].r>=base) point--;
        ans+=(point+1);
    }
    return ans;
}

long long get_jin1(vector<node>&a,vector<node>&b,long long base) //处理进位为1的使当前位为4的答案
{
    int point=0;long long ans=0;
    int siz=b.size();
    for(int i=a.size()-1;i>=0;i--) {
        while(point<=siz-1&&a[i].r+b[point].r<base) point++;
        ans+=(b.size()-point);
    }
    return ans;
}


int main()
{
    int t;scanf("%d",&t);
    while(t--) {
        a.clear();b.clear();
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&val[i]);
        solve(val+1,n/2,a);
        solve(val+1+n/2,n-(n/2),b);
        long long base=1,ans=0;
        for(int w=0;w<=8;w++) {
            for(int i=0;i<10;i++) c[i].clear(),d[i].clear();
            for(int i=0;i<a.size();i++) c[a[i].l%10].push_back(node{a[i].l/10,a[i].r});
            for(int i=0;i<b.size();i++) d[b[i].l%10].push_back(node{b[i].l/10,b[i].r});
            for(int i=0;i<10;i++) {              //枚举左半边的和的当前位的数
                int k1=(14-i)%10,k2=(13-i)%10;   //求右半边对应的和的当前位的数,k1表示在不进位的情况下的值,k2表示在后面有进位的情况下的需要的值
                ans+=get_jin0(c[i],d[k1],base)+get_jin1(c[i],d[k2],base);
            }
            int now=0;
            for(int i=0;i<10;i++) for(int j=0;j<c[i].size();j++) a[now++]=node{c[i][j].l,c[i][j].r+i*base};
            now=0;
            for(int i=0;i<10;i++) for(int j=0;j<d[i].size();j++) b[now++]=node{d[i][j].l,d[i][j].r+i*base};
            base*=10;
        }
        printf("%lld\n",ans);    
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值