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 lecontains 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 caseyou printed Ja, on the second line print four integers between 1 and n: a, b, c and d.
Example
vier.in vier.out
5 Ja2 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