Petrozavodsk Summer Training Camp 2016 Problem I. Vier 随机化+枚举

12 篇文章 0 订阅
3 篇文章 0 订阅

Problem I. Vier


Input le: vier.in
Output le: vier.out
Time limit: 2 seconds
Memory limit: 256 mebibytes


The online game you've built in problem "Oha" involves n types of monsters. The monster types are
numbered from 1 to n, and a monster of i-th type has strength i and magical ability PAI[i]. All magical
abilities are di erent integers between 1 and n, inclusive, in other words, PAI is a permutation. For
simplicity, you have generated this permutation uniformly at random.
Now you need to choose the starting teams of monsters for the two sides of the game. Each side must
have exactly two monsters in the starting team (they can be of the same type), and the starting teams
must be di erent. However, in order for the game to be balanced, the starting teams must have the same
total strength modulo n and the same total magical ability modulo n.
More formally, you need to nd four integers a, b, c and d between 1 and n such that:
1. a + b == c + d (mod n), and
2. PAIa + PAIb == PAIc + PAId (mod n).
Note that the above statements are trivially true when a = c and b = d, or when a = d and b = c. You
need to nd any other solution, or report that there isn't any. Note that it's allowed for some of the four
integers to coincide | the only restriction is that they can't coincide in the two ways described in the
rst sentence of this paragraph.


Input

The rst line of the input le contains one integer n, 2 <= n <= 10^6. The second line of the input le
contains n distinct integers, each between 1 and n. The i-th of those integers gives the value of PAIi.
It is guaranteed that the permutation was picked uniformly at random out of all permutations of n
integers.


Output

If a non-trivial solution exists, print Ja on the rst line of the output le, otherwise print Nein. In case
you printed Ja, on the second line print four integers between 1 and n: a, b, c and d.


Example

vier.in                      vier.out

5                                   Ja
2 4 3 5 1                     5 5 1 4


Note

There are 50 non-sample testcases in this problem.


Source

Petrozavodsk Summer Training Camp 2016
Day 5: Petr Mitrichev Contest 14, Saturday, August 27, 2016

Problem I. Vier


My Solution

题意:给出序列PAI[i],求是否存在a、b、c、d,使得1. a + b == c + d (mod n), and 2. PAIa + PAIb == PAIc + PAId (mod n).


 随机化+枚举

题目中特意描述了数据是随机均匀的,所以可以用随机化,在尽可能均匀的时间内求出答案。

每次随机一个x == a + b == c + d,然后枚举判断是否存在 PAIa + PAIb == PAIc + PAId (mod n).

虽然不知道怎么证明,但确实可以在比较低的时间复杂度内求出答案。

此外这题由于题目中提到数据是完全随机出的,所以理论上完全暴力枚举也是可以通过测试的但可能有极端的时间消耗,相对而言随机化的时候复杂度是比较稳定的。


#include <iostream>
#include <cstdio>
#include <ctime>
#include <cstring>
#include <cstdlib>
using namespace std;
typedef long long LL;
const int MAXN = 1e6 + 8;

template <class T>
inline void cinn(T &ret)
{
    char c=getchar();
    while(c<'0'||c>'9')
        c=getchar();
    ret=c-'0';
    while(c=getchar(),c>='0'&&c<='9')
        ret=ret*10+(c-'0');
}

int a[MAXN], f[MAXN];
bool vis[MAXN];

int main()
{
    srand(time(0));
    #ifdef LOCAL
    freopen("i.txt", "r", stdin);
    //freopen("i.out", "w", stdout);
    int T = 1;
    while(T--){
    #endif // LOCAL
    //ios::sync_with_stdio(false); cin.tie(0);

    int n, i, sum, u, ansa = -1, ansb = -1, ansc = -1, ansd = -1;
    cinn(n);
    for(i = 1; i <= n; i++){
        cinn(a[i]);
    }
    while(true){
        sum = rand() % n;
        sum += 1;
        if(vis[sum]) continue;

        vis[sum] = true;
        memset(f, 0, sizeof f);
        for(i = 1; i <= n; i++){
            if(i < sum){
                u = a[i] + a[sum - i];
                while(u >= n) u -= n;
                if(f[u]){
                    if(f[u] == i || f[u] == sum - i) continue;
                    ansa = i;
                    ansb = sum - i;
                    ansc = f[u];
                    if(f[u] < sum){
                        ansd = sum - f[u];
                    }
                    else if(f[u] == sum){
                        ansd = n;
                    }
                    else{
                        ansd = n + sum - f[u];
                    }
                    break;
                }
                f[u] = i;
            }
            else if(i == sum){
                u = a[i] + a[n];
                while(u >= n) u -= n;
                if(f[u]){
                    if(f[u] == i || f[u] == n) continue;
                    ansa = i;
                    ansb = n;
                    ansc = f[u];
                    if(f[u] < sum){
                        ansd = sum - f[u];
                    }
                    else if(f[u] == sum){
                        ansd = n;
                    }
                    else{
                        ansd = n + sum - f[u];
                    }
                    break;
                }
                f[u] = i;
            }
            else{
                u = a[i] + a[n + sum - i];
                while(u >= n) u -= n;
                if(f[u]){
                    if(f[u] == i || f[u] == n + sum - i) continue;
                    ansa = i;
                    ansb = n + sum - i;
                    ansc = f[u];
                    if(f[u] < sum){
                        ansd = sum - f[u];
                    }
                    else if(f[u] == sum){
                        ansd = n;
                    }
                    else{
                        ansd = n + sum - f[u];
                    }
                    break;
                }
                f[u] = i;
            }
        }
        if(ansa != -1) break;
    }
    printf("Ja\n%d %d %d %d\n", ansa, ansb, ansc, ansd);


    #ifdef LOCAL
    cout << endl;
    }
    #endif // LOCAL
    return 0;
}



  Thank you!

                                                                                                                                             ------from ProLights

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值