Codeforces Round #238 (Div. 1)__Toy Sum

题目链接

  • 题目大意:
    1到1e6数字中,有A、B两个集合,A中的每个数减一的和与B中数乘以负一加1e6(1e6 - x)的和相同。现在给n个A集合中的数,求B的数(任意一组即可)
  • 思路:
    比赛时看大家都是很快1A,差不多想到了是找规律的构造。苦于一直想不到方法。。。。
    这个题元素之间是没有联系的(乍一看),那么如果可以对于每个元素都能找到等价的就可以。先想到的自然是分拆成两个数的和,可是也不能保证一定能分,如果不能分拆,那么就麻烦了。所以应该换一种思路:找到每个元素的“替代品”。
    对于数x,计算和的时候变成x-1,对应的B中的数应该是1e6-x+1,所以如果这个数不在A中就可以等价了。问题来了,如果这个数存在了呢?考虑一下,这个时候我们有数x和数1e6-x+1,这两个数是有联系的(打破了一开始的判断),那么这时候就应该把有联系的数放在一起考虑。他俩的和应该是1e6+1,这里就应该敏感了,与x是无关的!!!也就是说,这样的数的和是一定的,那么这一对数就可以用其他类似的数对(一个为x,一个为1e6-x+1)来代替。然后要考虑,这个代替是否一定成立呢?显然,给定的数只有5 * 1e5,最多有2.5 * 1e5对这样的,肯定会剩下而且够用。到此,分析结束。
  • 关键:
    认识到是用构造法;分析出每个数如何找到对应的数;对于特殊的数对如何处理
const int MAXN = 1000010;

int vis[MAXN];
const int MID = 1000001;

int main()
{
//    freopen("in.txt", "r", stdin);
    int n, t;
    while (~RI(n))
    {
        CLR(vis, 0);
        REP(i, n)
        {
            RI(t);
            vis[t]++;
        }
        vector<int> ans;
        int need = 0;
        FE(i, 1, 1000000)
        {
            if (vis[i])
            {
                if (!vis[MID - i])
                    ans.push_back(MID - i);
                else
                    need++;
            }
        }
        need /= 2;

        int len = ans.size();
        REP(i, len)
            vis[ans[i]]++;
        for (int i = 1; need && i <= 1000000; i++)
        {
            if (!vis[i] && !vis[MID - i])
            {
                need--;
                ans.push_back(i);
                ans.push_back(MID - i);
            }
        }
        if (need)
            ans.push_back(1000000);
        len = ans.size();
        WI(len);
        REP(i, len)
        {
            if (i != 0)
                putchar(' ');
            printf("%d", ans[i]);
        }
        puts("");
    }
    return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值