2017百度之星 复赛

24 篇文章 0 订阅
10 篇文章 0 订阅

作为一只菜鸡,这可能是我OI生涯中最后一次打百度之星了,希望明年这个时候能不退役(虽然不大可能)

开始贴题解吧。会持续更新。

1001 Arithmetic of Bomb
煞笔模拟题,1A

#include<cstdio>
#include<algorithm>
#include<cstring>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int N=1e5+5;
const int mo=1e9+7;
int n,m;
char s[N],s1[N],ch[N],s2[N];
int main()
{
    int cas;
    scanf("%d",&cas);
    while (cas--)
    {
        scanf("%s",s);
        int len=strlen(s),m=0,i=0;
        while (i<=len-1)
        {
            if (s[i]=='(')
            {
                int cnt=0;
                i++;
                while (s[i]!=')')
                {
                    ch[++cnt]=s[i];
                    i++;
                }
                i+=3;
                int cnt1=0;
                while (s[i]!=')')
                {
                    s2[++cnt1]=s[i];
                    i++;
                }
                int tim=0,c=1;
                fd(j,cnt1,1)tim=(tim+1ll*(s2[j]-'0')*c%mo)%mo,c=1ll*c*10%mo;
                while (tim--)
                {
                    fo(j,1,cnt)s1[++m]=ch[j];
                }
                i++;
            }
            else
            {
                s1[++m]=s[i];
                i++;
            }
        }
        int ans=0,c=1;
        fd(i,m,1)
        {
            ans=(ans+1ll*(s1[i]-'0')*c%mo)%mo;
            c=1ll*c*10%mo;
        }
        printf("%d\n",ans);
    }
}

1002
此题目前为止也只有6个人,一开始没注意到原来展开也可以是个int以内的数,直接像1001展开1e9就炸了= =要用快速幂合并,其实快速幂挺容易想到,但是整个题就是这个合并,是个码农题。口头ACqwq。

1003
蓝桥杯原题,统计原理,打个表一切就出来了,要注意的是从边角出发和从中间出发步数不一样,不能随便不经思考下结论。
http://blog.csdn.net/yanghui07216/article/details/50490089

#include<stdio.h>  
#include<string.h>  
#include<algorithm>  
#define ll long long  
#define M 1000000007  
using namespace std;  
ll a[200010];  
ll b[20010];  
int main()  
{  
    int n,i;  
    int cas;
    scanf("%d",&cas);
    while (cas--)
    {  
        scanf("%d",&n);
        b[1]=1;  
        for(i=2;i<=n;i++)  
            b[i]=(b[i-1]*2%M);  
        a[1]=1;a[2]=6;  
        for(i=3;i<=n;i++)  
            a[i]=(b[i]+2*a[i-1]+4*a[i-2])%M;  
        ll sum=4*a[n];  
        for(i=2;i<n;i++)  
        {  
            sum+=(((8*a[n-i]*b[i-1])%M+8*b[n-i]*a[i-1])%M)%M;  
            sum%=M;  
        }  
        if(n==1)  
            sum=2;  
        printf("%lld\n",sum);  
    }  
    return 0;  
}  

1004 留坑,不会做

1005数位dp,很久没打各种被坑,爽的一匹。
记录dp[i][j][k]表示做到第i位,前一个数为j,k表示前面是递增还是不递增,0/1状态。
记忆化搜索,由于很久没做过数位dp很多细节都忘记了,现在重新回顾一下,dalao可以跳过。
假如现在是递增状态,那么当前位的数必须是pre到当前位能取的最高数,设为end,那么明显,假如前一位未取满,那么这一位end随便搞,否则就不能超过原字符串中的数字。
假如不是,那么枚举他是否转移到递增状态,转移到很简单。
如果不转移,还是不递增,那么正常转移,当然,有一种特殊情况,就是前一位是0,这一位还是0,这种情况要打标记特殊处理,相当于直接全部为0。
最后我们对于不限制的情况用dp数组存一下,受限制的情况用dfs算就好了

#include<cstdio>
#include<algorithm>
#include<cstring>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int N=205;
const int mo=1e9+7;
typedef long long ll;
ll dp[N][15][5];
ll p[N];
int num[N];
inline ll dfs(int pos,int status,int pre,int limit)
{
    if (pos<1)return 1;
    if (!limit&&dp[pos][pre][status]!=-1)
    return dp[pos][pre][status];
    int end=limit?num[pos]:9;
    ll ans=0;
    if(status)
    {
        fo(i,pre,end)
        {
            ans+=dfs(pos-1,status,i,limit&&i==end);
            ans%=mo;
        }
    }
    else
    {
        fo(i,0,end)
        {
            if (i>pre)
            ans=(ans+dfs(pos-1,1,i,limit&&i==end))%mo;
            else
            {
                if (!i&&pre==10)ans+=dfs(pos-1,0,10,limit&&i==end);
                else ans+=dfs(pos-1,0,i,limit&&i==end);
                ans%=mo;
            }
        }

    }
    if (!limit)dp[pos][pre][status]=ans;
    return ans;
}
inline ll solve(char s[])
{
    int len=strlen(s);
    fo(i,0,len-1)
    {
        num[len-i]=s[i]-'0';
    }
    return dfs(len,0,10,1);
}
int main()
{
    char s[N];
    memset(dp,-1,sizeof(dp));
    int cas;
    scanf("%d",&cas);
    while (cas--)
    {
        scanf("%s",s);
        printf("%lld\n",solve(s)-1);
    }
}

1006 题解tag是折半状压网络流
不存在的,不会。留坑也填不了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值