E. The LCMs Must be Large(思维)

 题目链接: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\n");
40                 return 0;
41             }
42         }
43     }
44     printf("possible\n");
45     return 0;
46 }

猜你喜欢

转载自www.cnblogs.com/letlifestop/p/10901836.html