SRM 546 div2

1 篇文章 0 订阅
1 篇文章 0 订阅

连续3场混迹div2了,还是绿的。。。委屈

 

250pt

     数据比较小,可以开个数组搞。。。大的话可以用map

550pt

     数据比较小,可以直接暴搜1000*1000的格子判断。。。大的话就分情况讨论吧,感觉好复杂的样纸,还容易挂掉。。。

1000pt

     这题跪了。。。开始想用DP,没怎么想清楚就开始乱搞了。。。。然后浪费了30min。。。

    之后改成构造,把每一位前面的d1和d2个数记记下来,然后从最低位开始找,找到最低可以开始构造的位数i,然后再判断可行不(判断如果后i位全取最大可以比N大么),如果不行,就把i的前一位+1,然后再重复操作即可,知道找到答案

     其实这题不难的,写完一直过不完sample,居然是拼写错误。。。跪跪跪

     然后跪system test。。。注意前导0啊。。。

//1000pt的代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<map>
#include<vector>

#define ll long long

using namespace std;

int cc1[20],cc2[20],tot=0;
ll a[25],b[1000000];

void cal(ll x,int tc1,int tc2,int d1,int d2)
{
    //cout<<x<<" "<<tc1<<" "<<tc2<<" "<<d1<<" "<<d2<<endl;
    if((tc1==0)&&(tc2==0)){b[++tot]=x;return;}
    if(tc1>0)if(d1!=0||d1==0&&x!=0)cal(x*10+d1,tc1-1,tc2,d1,d2);   //前导0要除掉啊。。。
    if(tc2>0)cal(x*10+d2,tc1,tc2-1,d1,d2);
}

ll find(ll N,ll M,int tc1,int tc2,int d1,int d2)
{
    cal(0,tc1,tc2,d1,d2);
    int i,k=tc1+tc2;
    //for(i=1;i<=tot;i++)cout<<b[i]<<endl;
    for(i=1;i<=tot;i++)
    if(N/a[k]*a[k]+b[i]>M)break;
    return N/a[k]*a[k]+b[i];
}
class FavouriteDigits
{
public:
long long findNext(long long N,int d1,int c1,int d2,int c2)
{
    ll temp,k,M=N;
    if(d1>d2){swap(d1,d2);swap(c1,c2);}
    int len,i,j,x;
    a[0]=1;
    for(i=1;i<=18;i++)a[i]=a[i-1]*10;
    while(1)
    {
        len=1;
        temp=N/10;
        while(temp){len++;temp/=10;}
        cc1[len]=cc2[len]=0;
        for(i=len-1;i>=0;i--)
        {
            x=N/a[i]%10;
            cc1[i]=cc1[i+1];
            cc2[i]=cc2[i+1];    //开始直接写成cc2[1],WA了好久,囧
            if(x==d1)cc1[i]++;
            if(x==d2)cc2[i]++;
        }
        if(cc1[0]>=c1&&cc2[0]>=c2)return N;
        int tc1,tc2;
        for(i=1;i<=len;i++)
        {
            if(cc1[i]>=c1)tc1=0;
            else          tc1=c1-cc1[i];
            if(cc2[i]>=c2)tc2=0;
            else          tc2=c2-cc2[i];
            if(tc1+tc2>i)continue;
            //cout<<i<<endl;
            k=0;
            for(j=1;j<=tc2;j++)k=k*10+d2;
            for(j=1;j<=tc1;j++)k=k*10+d1;
            if(N/a[i]*a[i]+k<M)break;
            //cout<<N<<endl;
            return find(N,M,tc1,tc2,d1,d2);
        }
        if(i>len)i=len;
        N=(N/a[i]+1)*a[i];
    }
    return -1;
}
};

顺便ym跟我一个房间cha了3个人的大神。。。人家的代码我都看不懂怎么cha。。。

    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值