加了些数论知识 先看下剩余类的概念
一个整数被正整数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 ",g); 88 else 89 printf("-1 "); 90 return 0; 91 }