Codeforces_43C_Lucky Tickets(贪心)

题型:数论


题意

      有n个纸片,每张纸片上有一个数,两张纸片拼接起来形成一个新的数,如歌这个数能够被3整除,那么就称这个数是Lucky Tickets。现在问最多拼出多少个Lucky Tickets。(拼过的纸片不能再拼)。


分析

根据性质,当一个数各个位上的数之和能够被3整除,则这个数能被3整除。

此题用贪心求解可过,下面证明贪心的正确性。

设有四个数a,b,c,d,若(a+b)%3=0,(a+c)%3=0,(c+d)%3=0,那么(b+d)%3=0。

证明:                             (a+b)%3=0                               ①

                                        (a+c)%3=0                               ②

                                        (c+d)%3=0                               ③

           ②合并得:       ((a+b)%3+(a+c)%3)%3=0

                                   → (2a+b+c)%3=0                         ④

           合并得:       ((a+c)%3+(c+d)%3)%3=0

                                   → (2c+a+d)%3=0                         ⑤

           ⑤合并的:       (3(a+c)+b+d)%3=0

                                   → (3(a+c)%3+(b+d)%3)%3=0

                                   ∵ 3(a+c)%3=0

                                   ∴ (b+d)%3=0

           得证。

上述证明说明:选ab拼接和cd拼接,与选ac拼接和bd拼接是一样的,所以只需贪心拼接即可。


代码

#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#define INF 0x7f7f7f7f
using namespace std;

struct Number {
    char str[10];
    int sum;
} a[12345];
bool vis[12345];
int n;

int main() {
    while(~scanf("%d",&n)) {
        for(int i=0; i<n; i++) {
            scanf("%s",a[i].str);
            a[i].sum=0;
            int len=strlen(a[i].str);
            for(int j=0; j<len; j++) {
                a[i].sum+=a[i].str[j]-'0';
            }
        }
        memset(vis,true,sizeof(vis));
        bool find=false;
        int ans=0;
        for(int i=0; i<n-1; i++) {
            if(vis[i]==false) continue;
            for(int j=i+1; j<n; j++) {
                if(vis[j]==false) continue;
                if((a[i].sum+a[j].sum)%3==0) {
                    ans++;
                    vis[i]=false;
                    vis[j]=false;
                    find=true;
                    break;
                }
            }
            if(find) continue;
        }
        printf("%d\n",ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值