【codejam2019 Round1A】Golf Gophers 题解

题目大意

  这是一道交互题。
  现在有若干只地鼠,你只知道地鼠数量 $\leq M$,你要把这个数量猜出来。
  你有 18 个风扇。每天初始,你给每个风扇设定它的叶片数 $b_i$(2 到 18 之间,从 0 开始标号),然后都让 0 号叶片指向正下。接着,每只地鼠独立地、等概率地选择一个风扇,把它的叶片往前拨一位(即原来是 $j$ 号叶片向下的现在变成 $(j+1)\bmod b_i$ 号叶片向下)。
  你告诉电脑 $b$ 序列,它告诉你这天结束时各风扇指向正下的叶片编号。
  你要在至多 $N$ 天之内猜出来。

  $Task1: N=365,\ \ M=100$
  $Task2: N=7,\ \ M=10^6$

题解

  Task1:
  没想出来。。。

  Task2:

看到 $N=7$,马上想到 $18$ 以内恰好只有 $7$ 个质数,用这 $7$ 个质数做模数,然后解中国剩余定理!!
——Zayin

  他从看完题到想出这一串东西总共用了 10s

  对于每一天,所有的风扇叶片数都取同一个模数 $p$,那么这一天你把最终状态加起来,就知道了地鼠数量$\mod p$ 的值。
  7 天就把 $2、3、5、7、11、13、17$ 全部试一遍,这就有了 7 个同余方程。然后跑 CRT 就行了。
  根据 CRT,这个方程组在 $23517=510510$ 内有唯一解。

  好像不够大?那把 $2$ 换成 $16$、$3$ 换成 $9$ 就可以啦!

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include<bits/stdc++.h>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;

typedef long long LL;

const int maxs=50005, maxlen=55;

int n,m,p[7]={5,7,11,13,17,16,9};

LL ny(LL x,int pi)
{
fo(i,1,p[pi]-1) if (x*i%p[pi]==1) return i;
}

int T;
int main()
{
LL P=1;
fo(i,0,6) P*=p[i];

scanf("%d%d%d",&T,&n,&m);
fo(ti,1,T)
{
LL ans=0;

fo(i,0,6)
{
LL a=0;

fo(j,1,18) printf("%d ",p[i]);
puts("");
fflush(stdout);

fo(j,1,18)
{
int x;
scanf("%d",&x);
(a+=x)%=p[i];
}

(ans+=a*(P/p[i])%P*ny(P/p[i],i))%=P;
}

printf("%lld\n",ans);
fflush(stdout);
int res;
scanf("%d",&res);
}
}