13074/HDU6682 Rikka with Mista

Rikka with Mista

时间限制: 7 Sec 内存限制: 512 MB
题目描述
Rikka is a fervent fan of JoJo’s Bizarre Adventure. As the last episode of Golden Wind has been aired, Rikka, with the help of Yuta, sets up this problem to express the love to Mista.
Mista’s lucky number is 4. Today, 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 ith card are wi and 0.
Firstly, Mista puts these n cards to table one by one. For each card, the probability of the wi side to be upward is 1/2, and these probabilities are independent with each other. As a result, there are n integers on the table. Mista then sums up all these integers and counts the number of 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 2n possible states in total. You are required to calculate the sum of the results for all these situations.

输入
The first line of the input contains a single integer T(4≤T≤4), the number of test cases.
For each test case, the first line contains a single integer n(4≤n≤40), the number of the cards.
The second line contains n integers w1,…,wn(4≤wi≤44444444), the positive numbers on the cards.

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

样例输入
4
4
4 4 4 4
4
4 4 44 44
4
4 44 44 4444
4
444 44444 44444 4444444
样例输出
4
10
24
38

提示
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.

方法

折半搜索+桶排序+双指针查找
n的个数为40,直接枚举会t,不难想到折半搜索的方法
然后依次按照每一位进行排序,使用双指针查找i+j在该位大于等于4小于5或者大于等于14小于15的情况
双指针可以使用是因为对于增加的i,符合条件的j是一个连续的区间,并且区间左右端点只可能左移而不会右移
对每一位排序的方法可以利用桶排序进行优化,省去一个log的复杂度

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N=2048576+5;
const int M=400+5;

ll ans[5][N];
ll a[5][M];
ll tp[10][N];   //桶排
int n1,n2;
void dfs(ll* a,int i,ll now,int n,ll *ans,int &k)
{
    if(i==n+1)
    {
        ans[++k]=now;
        return;
    }
    dfs(a,i+1,now,n,ans,k);
    dfs(a,i+1,now+a[i],n,ans,k);
}
void msort(ll *a,int n,ll p)
{
    for(int i=0;i<=9;i++) tp[i][0]=0;
    for(int i=1;i<=n;i++)
    {
        int x=(a[i]/p)%10;
        tp[x][++tp[x][0]]=a[i];
    }
    n=0;
    for(int i=0;i<=9;i++)
        for(int j=1;j<=tp[i][0];j++)
            a[++n]=tp[i][j];
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    int _;
    cin>>_;
    while(_--){
        int n;
        cin>>n;
        int m1=n/2;
        int m2=n-m1;
        for(int i=1;i<=m1;i++)
            cin>>a[0][i];
        for(int i=1;i<=m2;i++)
            cin>>a[1][i];
        n1=n2=0;
        dfs(a[0],1,0,m1,ans[0],n1);
        dfs(a[1],1,0,m2,ans[1],n2);

        /*for(int i=1;i<=n1;i++)
            cout<<ans[0][i]<<' ';
        cout<<endl;
        for(int i=1;i<=n2;i++)
            cout<<ans[1][i]<<' ';
        cout<<endl;*/

        ll p=1,anss=0;
        for(int ii=0;ii<=9;ii++,p*=10){
            msort(ans[0],n1,p);
            msort(ans[1],n2,p);

            int l=n2,r=n2;
            for(int i=1;i<=n1;i++){
                while(l>=1&&(ans[0][i]%(p*10)+ans[1][l]%(p*10)>=4*p)) l--;
                while(r>=1&&(ans[0][i]%(p*10)+ans[1][r]%(p*10)>=5*p)) r--;
                anss+=r-l;
            }
            l=n2,r=n2;
            for(int i=1;i<=n1;i++){
                while(l>=1&&(ans[0][i]%(p*10)+ans[1][l]%(p*10)>=14*p)) l--;
                while(r>=1&&(ans[0][i]%(p*10)+ans[1][r]%(p*10)>=15*p)) r--;
                anss+=r-l;
            }


        }

        cout<<anss<<endl;


    }
}

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值