2014年江北区】这是一道动规题(seq.pas/c/cpp)

题目描述

在一个给定的序列中,寻找一个最长的子序列(不要求连续),使得该子序列的和除以3的余数为0。

输入

从文件 seq.in 中读入数据。

第一行n,表示共有n个数。
第二行共n个数,用一个空格隔开。

输出

输出到文件 seq.out 中。

输出就一个整数,所求子序列的最大长度。 

样例输入 复制
6
1 2 2 1 2 5
样例输出 复制
5
数据范围限制

存在子序列1 2 2 2 5符合条件

提示

对于20%的数据,n<=10
对于60%的数据,n<=1000
对于100%的数据,n<=100000,序列中的数<=100000。

思路:

这道题其实就是道数学题,除了输入,其他地方连循环都不用。

AC代码:

#include<bits/stdc++.h>  // 包含常用头文件
using namespace std;
int n,s;  // n:数字个数 s:所有数字总和
int a;  // 临时变量,用于读取每个数字
int n1[10];  // 数组n1[0],n1[1],n1[2]分别记录余数为0,1,2的数字个数

int main()
{
    freopen("seq.in","r",stdin);  // 重定向输入到文件
    freopen("seq.out","w",stdout);  // 重定向输出到文件
    scanf("%d",&n);  // 读取数字个数n
    for(int i=1;i<=n;i++)  // 循环读取每个数字
    {
        scanf("%d",&a);  // 读取当前数字
        s+=a,n1[a%3]+=1;  // 累加总和s,并统计余数分布
    }
    s%=3;  // 计算总和除以3的余数
    
    if(s==0)  // 如果总和余0,直接取全部数字
    {
        printf("%d",n);
        return 0;
    }
    else if(s==1)  // 如果总和余1
    {
        if(n1[1]!=0)  // 优先去掉1个余1的数字
        {
            printf("%d",n-1);
            return 0;
        }
        else if(n1[2]>=2)  // 如果没有余1的数字,去掉2个余2的数字
        {
            printf("%d",n-2);
            return 0;
        }
    }
    else if(s==2)  // 如果总和余2
    {
        if(n1[2]!=0)  // 优先去掉1个余2的数字
        {
            printf("%d",n-1);
            return 0;
        }
        else if(n1[1]>=2)  // 如果没有余2的数字,去掉2个余1的数字
        {
            printf("%d",n-2);
            return 0;
        }
    }
    printf("%d",n);  // 如果无法调整,只能取全部数字
    return 0;
}
 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值