百度之星复赛题解


1001 Arithmetic of Bomb

 
Problem Description

众所周知,度度熊非常喜欢数字。

它最近在学习小学算术,第一次发现这个世界上居然存在两位数,三位数……甚至N位数!

但是这回的算术题可并不简单,由于含有表示bomb的#号,度度熊称之为 Arithmetic of Bomb。

Bomb Number中的bomb,也就是#号,会展开一些数字,这会导致最终展开的数字超出了度度熊所能理解的范畴。比如”(1)#(3)”表示”1”出现了3次,将会被展开为”111”,

同理,”(12)#(2)4(2)#(3)”将会被展开为”12124222”。

为了方便理解,下面给出了Bomb Number的BNF表示。

<bomb number> := <bomb term> | <bomb number> <bomb term>
<bomb term> := <number> | '(' <number> ')' '#' '(' <non-zero-digit> ')'
<number> := <digit> | <digit> <number>
<digit> := '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
<non-zero-digit> := '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'

请将Bomb Number中所有的#号展开,由于数字可能很长,结果对 1 000 000 007 取模。

Input

第一行为T,表示输入数据组数。

每组数据包含一个Bomb Expression。

  • 1≤T≤100

  • 1≤length(Bomb Number)≤1000

Output

对每组数据输出表达式的结果,结果对 1 000 000 007 取模。

Sample Input
4
1
(1)#(3)
(12)#(2)4(2)#(3)
(12)#(5)
Sample Output
1
111
12124222
212121205


简单的模拟题


#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<queue>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<stack>
#include<set>
#include<iomanip>
//#define mem(dp,a) memset(dp,a,sizeof(dp))
//#define fo(i,n) for(int i=0;i<(n);i++)
//#define INF 0x3f3f3f3f
#define fread() freopen("data.txt","r",stdin)
#define fwrite() freopen("out.out","w",stdout)
using namespace std;
typedef  long long ll;
const ll MOD  = 1000000007;

int dir[4][2] = { {1,0} , {-1,0} , {0,-1}, {0,1} };


string s;
string re;

string st,tn;



int T;
int main()
{
    ios_base::sync_with_stdio(false);
//    fread();
//    freopen("input.in","r",stdin);
//    freopen("output.out","w",stdout);
//    while(cin >> n)
    cin >> T;
    while(T--)
    {
        re.clear();
        cin >> s;
        int ind=  0;
        for(;ind<s.size();ind++)
        {
            if(s[ind]=='(')
            {
                st.clear();
                ind++;
                while(s[ind]!=')')
                {
                    st+=s[ind];
                    ind++;
                }
//                cout << st<<endl;
                ind+=3;

                tn.clear();
                while(s[ind]!=')')
                {
                    tn+=s[ind];
                    ind++;

                }
                ll num = atoll(tn.c_str());
                for(ll i =0;i<num;i++)
                {
                    re += st;
                }
            }
            else
            {
                re+=s[ind];
            }
        }
        ll ans = 0;
        for(int i=0;i<re.size();i++)
        {
            ans = (ans%MOD * 10)%MOD;
            ans += re[i]-'0';
            ans %=MOD;
        }
        cout << ans<<endl;
    }

    return 0;
}





1003 Pokémon GO

Problem Description

众所周知,度度熊最近沉迷于 Pokémon GO。

今天它决定要抓住所有的精灵球!

为了不让度度熊失望,精灵球已经被事先放置在一个2*N的格子上,每一个格子上都有一个精灵球。度度熊可以选择任意一个格子开始游戏,抓捕格子上的精灵球,然后移动到一个相邻的至少有一个公共点的格子上继续抓捕。例如,(2, 2) 的相邻格子有(1, 1), (2, 1) 和 (1, 2) 等等。

现在度度熊希望知道将所有精灵球都抓到并且步数最少的方案数目。两个方案被认为是不同,当且仅当两个方案至少有一步所在的格子是不同的。

Input

第一行为T,表示输入数据组数。

每组数据包含一个数N。

●1≤T≤100

●1≤N≤10000

Output

对每组数据输出方案数目,结果对 1 000 000 007 取模。

Sample Input
3
1
2
3
Sample Output
2
24
96



DP

原题:http://blog.csdn.net/u010126535/article/details/20651999


#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<queue>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<stack>
#include<set>
#include<iomanip>
//#define mem(dp,a) memset(dp,a,sizeof(dp))
//#define fo(i,n) for(int i=0;i<(n);i++)
//#define INF 0x3f3f3f3f
#define fread() freopen("data.txt","r",stdin)
#define fwrite() freopen("out.out","w",stdout)
using namespace std;
typedef  long long ll;
const ll N = 10005;
const ll MOD  = 1000000007;

ll a[N]={0};
ll b[N]={0};

ll re[N];

int T,n;
int main()
{
    ios_base::sync_with_stdio(false);
//    fread();
    re[1] = 2;
    b[1]=1;
    for (int i=2;i<=N;i++)
        b[i]=(b[i-1]*2%MOD);
    a[1]=1;a[2]=6;
    for (int i=3;i<=N;i++)
        a[i]=(2*a[i-1]+b[i]+4*a[i-2])%MOD;
    for(int k=2;k<=N;k++)
    {
        re[k]=4*a[k];
        for(int i=2;i<k;i++)
        {
            re[k]+=((8*b[k-i]*a[i-1])%MOD+(8*a[k-i]*b[i-1])%MOD)%MOD;
            re[k] %= MOD;
        }
    }

    cin >> T;
    while(T--)
    {
        cin >> n;
        cout<<re[n]<<endl;
    }


    return 0;
}









 1005 Valley Numer


众所周知,度度熊非常喜欢数字。

它最近发明了一种新的数字:Valley Number,像山谷一样的数字。

当一个数字,从左到右依次看过去数字没有出现先递增接着递减的“山峰”现象,就被称作 Valley Number。它可以递增,也可以递减,还可以先递减再递增。在递增或递减的过程中可以出现相等的情况。

比如,1,10,12,212,32122都是 Valley Number。

121,12331,21212则不是。

度度熊想知道不大于N的Valley Number数有多少。

注意,前导0是不合法的。

Input

第一行为T,表示输入数据组数。

每组数据包含一个数N。

● 1≤T≤200

● 1≤length(N)≤100

Output

对每组数据输出不大于N的Valley Number个数,结果对 1 000 000 007 取模。

Sample Input
3
3
14
120
Sample Output
3
14
119



数位DP

dp[位数][当前值][是否达到当前最大位][是否存在前置0]


#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const ll MOD =  1000000007;
const int N = 100 + 5;
char str[N];
ll dp[N][11][2][2];
int len;

ll DFS(int pos, int pre, int up, int limit,int t) {

    if (pos == len) {
        return 1;
    }
    ll &now = dp[pos][pre][up][t];
    if (!limit && now != -1) {
        return now;
    }
    ll ret = 0;
    int d = limit ? str[pos] - '0' : 9;



    for (int i=0; i<=d; ++i) {

        if (up)
        {
            if (i >= pre)
            {
                ret += DFS (pos + 1, i, 1&&!t, limit && i == d,i==0&&t);
                ret%=MOD;
            }
        }
        else
        {
            if (i <= pre)
            {
                ret += DFS (pos + 1, i, 0, limit && i == d,i==0&&t);
                ret%=MOD;
            }
            else
            {
                ret += DFS (pos + 1, i, 1&&!t, limit && i == d,i==0&&t);
                ret%=MOD;
            }

        }
    }
    if (!limit) {
        now = ret;
    }
    return ret;
}

int main() {
//    freopen("data.txt","r",stdin);
    int T; scanf ("%d", &T);
    while (T--) {
        scanf ("%s", str);
        len = strlen (str);
        memset (dp, -1, sizeof (dp));

        ll ans  = (DFS (0, 0, 1, 1,1) - 1 +MOD)%MOD;
        printf ("%I64d\n",ans);
    }
    return 0;
}



  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值