题目链接:https://codeforces.com/contest/1166/problem/E
题目大意:首先是n个数,然后有m次划分,每一次输入第一部分(下标),第一部分的补给为第二部分。然后问你能否(给a数组赋值)保证每一次的第一部分的数的lcm严格大于第二部分的lcm。
具体思路:
首先说一个性质,集合A为集合B的子集,那么lcm(A)<= lcm(B)。
反证法:
假设当前输入的m为2,我们将每一次输入分为
D1 S1
D2 S2.
假设D1与D2的交集为0 - > D2一定为S1的子集 - > D1一定为S2的子集 .
假设输入的样例合法。
那么lcm(D1)>lcm(S1)>= lcm(D2)> lcm(S2)> = lcm(D1)。
显然矛盾。
我们当前就可以得到这个结论,当任意两组的交集为0的时候,这个时候一定是不合法的。
接下来再去证明当两组的交集不是0的时候,一定是合法的。
我们假设a数组的数全部为1.当输入第i组的时候,D1中的数全部乘以第i个素数。以此类推。
这样的话,我们所有的Di的lcm都为前i个素数相乘的结果。
Si肯定为Di的真子集。
AC代码:
1 #include<bits/stdc++.h>
2 using namespace std;
3 # define ll long long
4 # define inf 0x3f3f3f3f
5 # define ull unsigned long long
6 const int maxn = 2e4+100;
7 const int N = 55;
8 int sto[N][maxn];
9 int num[maxn];
10 int main()
11 {
12 int n,m,tmp;
13 scanf("%d %d",&n,&m);
14 for(int i=1; i<=n; i++)
15 {
16 scanf("%d",&num[i]);
17 for(int j=1; j<=num[i]; j++)
18 {
19 scanf("%d",&tmp);
20 sto[i][tmp]++;
21 }
22 }
23 int flag=1;
24 for(int i=1; i<=n; i++)
25 {
26 for(int j=1; j<=n; j++)
27 {
28 int flag=1;
29 for(int k=1; k<=10000; k++)
30 {
31 if(sto[i][k]&&sto[j][k])
32 {
33 flag=0;
34 break;
35 }
36 }
37 if(flag)
38 {
39 printf("impossible
");
40 return 0;
41 }
42 }
43 }
44 printf("possible
");
45 return 0;
46 }