【codeforces 792C】Divide by Three

【题目链接】:http://codeforces.com/contest/792/problem/C

【题意】

让你删掉最少的数字使得剩下的数字%3==0

【题解】

看代码。。内置题解了现在。

【完整代码】

#include <bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define mp make_pair
#define ps push_back
#define fi first
#define se second
#define rei(x) scanf("%d",&x)
#define rel(x) scanf("%lld",&x)
#define ref(x) scanf("%lf",&x)

typedef pair<int,int> pii;
typedef pair<LL,LL> pll;

const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
const double pi = acos(-1.0);
const int N = 1e5+100;

char s[N];
int a[N],sum=0,len;
bool bo[N];

void out(){
    rep1(i,1,len)
        if (bo[i])
            cout << a[i];
    exit(0);
}

int main(){
    //freopen("F:\\rush.txt","r",stdin);
    memset(bo,true,sizeof bo);
    scanf("%s",s+1);
    len = strlen(s+1);
    rep1(i,1,len) {
        a[i] = s[i]-'0';
        sum=(sum+a[i])%3;
    }
    if (sum==0) out();//直接就符合题意了
    if (len==1) return puts("-1"),0;//接下来要删除1个数字了 所以如果刚好一个数字是不合法的
    rep1(i,2,len)//从第二个数字开始删就不会存在不合法的了
        if (a[i]%3==sum)
            bo[i] = false,out();
    if (a[1]%3==sum && (a[2]!=0||(a[2]==0&&len==2))) bo[1] = false,out();
    //第一个数字的话要求第二个数字不是0
    //或者长度为2,那么也只要删除一个数字;

    if (len<=2) return puts("-1"),0;
    //接下来要至少删除两个数字了,所以小于等于2个数字都不合法了,从后往前删
    //这样能保证先删除的两个数字它们是靠后的;
    //如果有删除第一个和前缀的0更优的话,a[1]%3==sum,不可能是删掉的两个数字之一,所以不会有删除多余的0
    //所以直接删两个和为sum肯定更优(或者不会差).
    //最后再考虑a[1]%3==sum和有前缀0的情况
    int d =0;//判断有没有两个可以删的了;
    rep2(i,len,1)
        if ((a[i]%3)==(3-sum)){//这是两个合起来删掉能变成%3为0的情况
            if (d){
                bo[i]=bo[d] = false;//删掉这两个数字
                int fir=0;//有没有找到第一个非0数字;
                rep1(j,1,len)
                    if (j!=i&&j!=d){
                        if (a[j]){
                            fir = 1;
                            break;
                        }
                        else//前面还没找到非0数字呢;
                            bo[j] = false;//是前缀0要删掉
                    }
                if (fir){//找到了前缀非0
                    out();
                }
                else{//没找到
                    //已经确定大于两个数字了
                    return puts("0"),0;
                }
            }
            else{
                d = i;
            }
        }
    //最后在再考虑删掉第一个数虽然可以但要删除前缀0的情况;
    if (a[1]%3==sum){
        bo[1] = false;
        int j =1;
        while (j+1<=len-1 && a[j+1]==0) j++,bo[j] = false;//要留一个0
        out();
    }
    puts("-1");
    //printf("\n%.2lf sec \n", (double)clock() / CLOCKS_PER_SEC);
    return 0;
}
posted @ 2017-10-04 18:44  AWCXV  阅读(318)  评论(0编辑  收藏  举报