Hdu 2015 Multi-University Training Contest6

1001

题面

SPJ
Problem Description
There are n soda sitting around a round table. soda are numbered from 1 to n and i-th soda is adjacent to (i+1)-th soda, 1-st soda is adjacent to n-th soda.

Each soda has some candies in their hand. And they want to make the number of candies the same by doing some taking and giving operations. More specifically, every two adjacent soda x and y can do one of the following operations only once:
1. x-th soda gives y-th soda a candy if he has one;
2. y-th soda gives x-th soda a candy if he has one;
3. they just do nothing.

Now you are to determine whether it is possible and give a sequence of operations.

Input
There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:

The first contains an integer n (1≤n≤10^5), the number of soda.
The next line contains n integers a1,a2,…,an (0≤ai≤10^9), where ai denotes the candy i-th soda has.

Output
For each test case, output “YES” (without the quotes) if possible, otherwise output “NO” (without the quotes) in the first line. If possible, then the output an integer m (0≤m≤n) in the second line denoting the number of operations needed. Then each of the following m lines contain two integers x and y (1≤x,y≤n), which means that x-th soda gives y-th soda a candy.

Sample Input

3
6
1 0 1 0 0 0
5
1 1 1 1 1
3
1 2 3

Sample Output

NO
YES
0
YES
2
2 1
3 2

题意

给n(10^5)个数,每个数[0,10^9]。
将这n个数连成环,即1之前为n,n之后是1。
现在有如下3种操作,要求对每一个数做如下操作1次以后,使得所有n个数都相等:
1.i 给 i+1 一,即 a[i]–,a[i + 1]++。
2.i + 1 给 i 一,即 a[i]++, a[i + 1]–。
3.任何事情都不干。

解析

可以发现,当第1个元素的状态确定了以后,之后的每个元素的状态也都确定了。。。
令残量 a[i] = a[i] - ave。
所以贪心只往一个方向操作,并枚举第1个元素的状态:
2给1 1,或者1给2 1,或者什么都不做。
然后来推之后的状态:
当目前的残量a[i]==1,则给后面1;
当目前的残量a[i]==-1,则从后面索取1;
当前残量a[i]==0,则啥都不做,。

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <climits>
#include <cassert>
#define LL long long
#define lson lo, mi, rt << 1
#define rson mi + 1, hi, rt << 1 | 1

using namespace std;

const int maxn = 1e5 + 10;

int a[maxn];
int c[maxn];
pair<int, int> ans[maxn];
int cnt;
int n;

bool check(int d)
{
    cnt = 0;
    memcpy(c, a, sizeof(a));
    c[0] -= d;
    c[1] += d;
    if (d == 1)
        ans[cnt++] = make_pair(0, 1);
    if (d == -1)
        ans[cnt++] = make_pair(1, 0);
    for (int i = 1; i < n; i++)
    {
        int j = (i + 1) % n;
        if (1 < abs(c[i]))
            return false;
        if (c[i] == 1)
        {
            c[i]--;
            c[j]++;
            ans[cnt++] = make_pair(i, j);
        }
        if (c[i] == -1)
        {
            c[i]++;
            c[j]--;
            ans[cnt++] = make_pair(j, i);
        }
    }
    return true;
}

bool ok()
{
    if (2 < abs(a[0]))
        return false;
    if (check(-1) || check(0) || check(1))
        return true;
    return false;
}

int main()
{
    #ifdef LOCAL
    freopen("in.txt", "r", stdin);
    #endif // LOCAL
    int ncase;
    scanf("%d", &ncase);
    while (ncase--)
    {
        scanf("%d", &n);
        LL sum = 0;
        bool zero = true;
        bool equa = true;
        for (int i = 0; i < n; i++)
        {
            scanf("%d", &a[i]);
            if (a[i])
                zero = false;
            if (i != 0 && a[i] != a[i - 1])
                equa = false;
            sum += a[i];
        }
        if (sum % n)
        {
            puts("NO");
            continue;
        }
        if (n == 1 || zero || equa)
        {
            printf("YES\n0\n");
            continue;
        }
        int ave = sum / n;
        for (int i = 0; i < n; i++)
            a[i] -= ave;
        if (ok())
        {
            puts("YES");
            printf("%d\n", cnt);
            for (int i = 0; i < cnt; i++)
            {
                printf("%d %d\n", ans[i].first + 1, ans[i].second + 1);
            }
        }
        else
        {
            puts("NO");
        }
    }
    return 0;
}

1003

题面

SPJ

Problem Description

There are m soda and today is their birthday. The 1-st soda has prepared n cakes with size 1,2,…,n. Now 1-st soda wants to divide the cakes into m parts so that the total size of each part is equal.

Note that you cannot divide a whole cake into small pieces that is each cake must be complete in the m parts. Each cake must belong to exact one of m parts.

Input

There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:

The first contains two integers n and m (1≤n≤105,2≤m≤10), the number of cakes and the number of soda.
It is guaranteed that the total number of soda in the input doesn’t exceed 1000000. The number of test cases in the input doesn’t exceed 1000.

Output

For each test case, output “YES” (without the quotes) if it is possible, otherwise output “NO” in the first line.

If it is possible, then output m lines denoting the m parts. The first number si of i-th line is the number of cakes in i-th part. Then si numbers follow denoting the size of cakes in i-th part. If there are multiple solutions, print any of them.

Sample Input

4
1 2
5 3
5 2
9 3

Sample Output

NO
YES
1 5
2 1 4
2 2 3
NO
YES
3 1 5 9
3 2 6 7
3 3 4 8

题意

给n和k,将1+2+…+n的蛋糕分给k个人,要求每个人最后的蛋糕和相等,输出方案。

解析

队友想的贪心,但是好像赛后在hduoj上过不了。
他自己打了1000组数据测试没有发现错误- -
DKW…

代码

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>
#include <cstdio>
#include <stack>
#include <queue>
#include <cmath>
#include <list>
#include <map>
#include <set>

#define ULL unsigned long long
#define LL long long
#define INF 0x3f3f3f3f
#define eps 1e-8
#define sum(i) ((1 + (i)) * (i) / 2)
using namespace std;
const int maxn = 100000 + 10;
bool vis[maxn];
vector<int>step[maxn];

int main()
{
#ifdef LOCAL
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
#endif // LOCAL
    int T;
    int cake, soda;
    scanf("%d", &T);
    while(T--)
    {
        for (int i =0; i < maxn; ++i)
            step[i].clear();

        scanf("%d%d", &cake, &soda);
        if (cake <= soda)
        {
            printf("NO\n");
            continue;
        }
        else if (sum(cake) / soda * soda != sum(cake))
        {
            printf("NO\n");
            continue;
        }
        else if (sum(cake) / soda < cake)
        {
            printf("NO\n");
            continue;
        }

        int need = sum(cake) / soda;
        memset(vis, false, sizeof(vis));

        for(int i = 0; i < soda; ++i)
        {
            int need = sum(cake) / soda;
            int now = cake;

            for (int j = cake; j >= 1 && need > 0; --j)
            {
                if (!vis[j])
                {
                    if (j <= need)
                    {
                        step[i].push_back(j);
                        vis[j] = true;
                        need -= j;
                    }
                }
            }
//            while(need > 0 && now > 0)
//            {
//                if (!vis[now])
//                {
//                    vis[now] = true;
//                    step[i].push_back(now);
//                    need -= now;
//                    now = min(need, cake);
//                }
//                else
//                    now--;
//            }
        }
        for (int i = 0; i < soda; ++i)
        {
            printf("%d", step[i].size());
            for (int j = 0; j < step[i].size(); ++j)
                printf(" %d", step[i][j]);
            printf("\n");
        }
    }
    return 0;
}

1008

题面

SPJ
Problem Description

There are n soda conveniently labeled by 1,2,…,n. beta, their best friends, wants to invite some soda to go hiking. The i-th soda will go hiking if the total number of soda that go hiking except him is no less than li and no larger than ri. beta will follow the rules below to invite soda one by one:
1. he selects a soda not invited before;
2. he tells soda the number of soda who agree to go hiking by now;
3. soda will agree or disagree according to the number he hears.

Note: beta will always tell the truth and soda will agree if and only if the number he hears is no less than li and no larger than ri, otherwise he will disagree. Once soda agrees to go hiking he will not regret even if the final total number fails to meet some soda’s will.

Help beta design an invitation order that the number of soda who agree to go hiking is maximum.

Input

There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:

The first contains an integer n (1≤n≤105), the number of soda. The second line constains n integers l1,l2,…,ln. The third line constains n integers r1,r2,…,rn. (0≤li≤ri≤n)
It is guaranteed that the total number of soda in the input doesn’t exceed 1000000. The number of test cases in the input doesn’t exceed 600.

Output

For each test case, output the maximum number of soda. Then in the second line output a permutation of 1,2,…,n denoting the invitation order. If there are multiple solutions, print any of them.

Sample Input

4
8
4 1 3 2 2 1 0 3
5 3 6 4 2 1 7 6
8
3 3 2 0 5 0 3 6
4 5 2 7 7 6 7 6
8
2 2 3 3 3 0 0 2
7 4 3 6 3 2 2 5
8
5 6 5 3 3 1 2 4
6 7 7 6 5 4 3 5

Sample Output

7
1 7 6 5 2 4 3 8
8
4 6 3 1 2 5 8 7
7
3 6 7 1 5 2 8 4
0
1 2 3 4 5 6 7 8

题意

选n(10^5)个人去旅游,他们的编号从1,2….,n。
然后每个人有一个愿意去旅游人数区间[l, r]。
这个区间代表,如果在邀请这个人的时候,当前去旅游的人数在这个区间内,那么这个人也会去旅游,旅游人数+1。
现在要你给出一个邀请这n个人去旅游的方案,使得去旅行的人最多。
输出最多人数,并输出邀请顺序方案。

解析

现在还是想不通开始的那种贪心策略为什么出错了。

对的贪心策略是一个一个选,如果nowperson == soda[i].l,就选soda[i].r中值最小的那个,然后继续。

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <climits>
#include <cassert>
#define LL long long
#define lson lo, mi, rt << 1
#define rson mi + 1, hi, rt << 1 | 1

using namespace std;
const int maxn = 1e6 + 10;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
const double pi = acos(-1.0);
const double ee = exp(1.0);

int nowperson;
struct Node
{
    int l, r;
    int id;
//    bool operator < (const Node& b)const
//    {
//        int t = abs(nowperson - l) + abs(nowperson - r);//abs(l - r); //
//        int tb = abs(nowperson - b.l) + abs(nowperson - b.r);//abs(b.l - b.r);//
//        if (l <= nowperson && nowperson <= r && b.l <= nowperson && nowperson <= b.r)
//        {
//            if (t == tb)
//            {
//                if (l == b.l)
//                    return r > b.r;
//                return l > b.l;
//            }
//            return t > tb;
//        }
//        if (l == b.l)
//            return r > b.r;
//        return l > b.l;
//    }
    bool operator < (const Node& b) const
    {
        return r > b.r;
    }
} soda[maxn];

bool cmp(Node a, Node b)
{
    return a.l < b.l;
}

bool vis[maxn];

int main()
{
    #ifdef LOCAL
    freopen("in.txt", "r", stdin);
    #endif // LOCAL
    int ncase;
    scanf("%d", &ncase);
    while (ncase--)
    {
        memset(vis, false, sizeof(vis));
        int n;
        int cnt = 0;
        priority_queue<Node> q;
        nowperson = 0;
        scanf("%d", &n);
        for (int i = 1; i <= n; i++)
        {
            scanf("%d", &soda[i].l);
            soda[i].id = i;
        }
        for (int i = 1; i <= n; i++)
        {
            scanf("%d", &soda[i].r);
        }
        sort(soda + 1, soda + n + 1, cmp);
        vector<int> ans;

        int t = 1;
        while (ans.size() < n)
        {
            while (nowperson == soda[t].l)
            {
                q.push(soda[t]);
                t++;
            }

            if (q.empty())
            {
                ans.push_back(soda[t].id);
                t++;
                continue;
            }

            while (!q.empty())
            {
                Node now = q.top();
                q.pop();
                if (nowperson <= now.r)
                {
                    nowperson++;
                    ans.push_back(now.id);
//                    vis[now.id] = true;
                    break;
                }
                else
                {
                    ans.push_back(now.id);
                }
            }
        }

        int sz = ans.size();
        printf("%d\n", nowperson);
//        for (int i = 1; i <= n; i++)
//        {
//            if (!vis[i])
//                ans.push_back(i);
//        }
//        sz = ans.size();
        for (int i = 0; i < sz; i++)
        {
            printf("%d%c", ans[i], i == sz - 1 ? '\n' : ' ');
        }
    }
    return 0;
}

1011

题面

Problem Description

soda has a set S with n integers {1,2,…,n}. A set is called key set if the sum of integers in the set is an even number. He wants to know how many nonempty subsets of S are key set.

Input

There are multiple test cases. The first line of input contains an integer T (1≤T≤10^5), indicating the number of test cases. For each test case:

The first line contains an integer n (1≤n≤10^9), the number of integers in the set.

Output

For each test case, output the number of key sets modulo 1000000007.

Sample Input

4
1
2
3
4

Sample Output

0
1
3
7

题意

给一个数字n(10^9),求从1,2,3…n,中选出若干个数,求和,问这个和是偶数的情况有多少种。

解析

奇数个数的和一定是奇数。
若所有数都取:

C(nn)+C(n1n)+C(n2n)+...+C(2n)+C(1n)+C(0n)=2n

但此时取出的和要为偶数,因此只能取C(n, 偶数),并且空集(0)不取,则-1。
所以为
2n21=2n11

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <climits>
#include <cassert>
#define LL long long
#define lson lo, mi, rt << 1
#define rson mi + 1, hi, rt << 1 | 1

using namespace std;
const int maxn = 1e6 + 10;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
const double pi = acos(-1.0);
const double ee = exp(1.0);

LL pow_mod(LL a, LL n, LL mod)
{
    if (n == 0)
        return 1;
    LL x = pow_mod(a, n >> 1, mod);
    LL res = x * x % mod;
    if (n % 2)
        res = res * a % mod;
    return res;
}

int main()
{
    #ifdef LOCAL
    freopen("in.txt", "r", stdin);
    #endif // LOCAL
    LL n;
    int ncase;
    scanf("%d", &ncase);
    while (ncase--)
    {
        scanf("%lld", &n);
        LL ans = pow_mod(2, n - 1, 1000000007) - 1;
        printf("%lld", ans % 1000000007);
        if (ncase)
            puts("");
    }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值