1682. Crazy Professor(并查集)

1628

加了些数论知识  先看下剩余类的概念

一个整数被正整数n除后,余数有n种情形:0,1,2,3,…,n-1,它们彼此对模n不同余。这表明,每个整数恰与这n个整数中某一个对模n同余。这样一来,按模n是否同余对整数集进行分类,可以将整数集分成n个两两不相交的子集。我们把(所有)对模n同余的整数构成的一个集合叫做模n的一个剩余类。

对于a%k=x b%k=y  若x!=y  a与b有边相连 则a的剩余类  与b的剩余类l里的元素也是可以相连的  即 a ->b->a+k->b+k->a 所以有环 

若x==y 则同一剩余类里元素都可以相连 a->a+k->a+2k->a 成环 且不会大于3*k

然后利用并查集就可以了 用vector存下可以与其满足对k取余为0的剩余类 枚举t t+k t+2*k时的情况 是不是形成 了环

 1 #include <iostream>

 2 #include<cstdio>

 3 #include<cstring>

 4 #include<stdlib.h>

 5 #include<vector>

 6 #include<algorithm>

 7 #include<cmath>

 8 using namespace std;

 9 #define N 300010

10 #define LL long long

11 vector<LL>q[N];

12 LL f[N];

13 LL find(LL x)

14 {

15     if(x!=f[x])

16     f[x] = find(f[x]);

17     return f[x];

18 }

19 int main()

20 {

21     LL i,j,k;

22     int flag = 0,g;

23     scanf("%lld",&k);

24     for(i = 0; i <= k*3; i++)

25     f[i] = i;

26     for(i = 0 ; i < k ; i++)

27     {

28         LL tt = (i*i)%k;

29         q[i].push_back((k-tt)%k);

30         q[(k-tt)%k].push_back(i);

31     }

32     for(i = 0 ; i < k ; i++)

33     sort(q[i].begin(),q[i].end());

34     for(i = 2; i <= k*3 ; i++)

35     {

36         int io = i%k;

37         int tt = unique(q[io].begin(), q[io].end()) - q[io].begin();

38         int t;

39         for(j = 0 ; j < tt ; j++)

40         {

41             t = q[io][j];

42             if(t<i&&t>0)

43             {

44                 int tx = find(i);

45                 int ty = find(t);

46 

47                 if(tx==ty)

48                 {

49                     flag = 1;

50                     break;

51                 }

52                 else

53                 f[tx] = ty;

54             }

55             if(t+k<i)

56             {

57                 int tx = find(i);

58                 int ty = find(t+k);

59                 if(tx==ty)

60                 {

61                     flag = 1;

62                     break;

63                 }

64                 else

65                 f[tx] = ty;

66             }

67             if(t+2*k<i)

68             {

69                 int tx = find(i);

70                 int ty = find(t+2*k);

71                 if(tx==ty)

72                 {

73                     flag = 1;

74                     break;

75                 }

76                 else

77                 f[tx] = ty;

78             }

79         }

80         if(flag)

81         {

82             g = i;

83             break;

84         }

85     }

86     if(flag)

87     printf("%d\n",g);

88     else

89     printf("-1\n");

90     return 0;

91 }
View Code

 

 

 

你可能感兴趣的:(SSO)