题目:传送门
大致题意:问是否存在两个整数 k1 和 k2 ,满足 k1 + ak1%n = k2+ ak2%n ;
思路: 显然,对于无穷区间我们是不能求解的,因此可以尝试着把无穷区间通过%n 运算,映射到区间 [ 0 , n -1 ] 。
设 k1 % n = i , 则有 i + x * n = k1 ,其中 x = k1 / n (向下取整)
k2 %n = j , 则有 j + y * n = k2 ,其中 y = k2 / n (向下取整)
k1 + ak1%n = k2+ ak2%n 可化为 i + x * n + ai = j + y + aj ;
对方程两边同时 %n ,得:( i + ai )% n = ( j + aj )% n ,其中 i 和 j 位于区间 [ 0 , n-1 ];
这道题就转化为 遍历 0 ~ n-1 ,算出所有( i + ai )% n 的值并判断是否有重复 (或者判断[ 0 ,n-1 ] 中 是否有数值未出现过,有数值重复 就意味着 有其他数值空缺 )、
1 #include<bits/stdc++.h> 2 /* 3 #include<cstdio> 4 #include<cmath> 5 #include<cstring> 6 #include<vector> 7 #include<cctype> 8 #include<queue> 9 #include<algorithm> 10 #include<map> 11 #include<set> 12 */ 13 #pragma GCC optimize(2) 14 using namespace std; 15 typedef long long LL; 16 typedef pair<int,int> pii; 17 typedef pair<double,double> pdd; 18 const int N=2e5+5; 19 const int M=3005; 20 const int inf=0x3f3f3f3f; 21 const LL mod=1e9+7; 22 const double eps=1e-9; 23 const long double pi=acos(-1.0L); 24 #define ls (i<<1) 25 #define rs (i<<1|1) 26 #define fi first 27 #define se second 28 #define pb push_back 29 #define mk make_pair 30 #define mem(a,b) memset(a,b,sizeof(a)) 31 LL read() 32 { 33 LL x=0,t=1; 34 char ch; 35 while(!isdigit(ch=getchar())) if(ch==‘-‘) t=-1; 36 while(isdigit(ch)){ x=10*x+ch-‘0‘; ch=getchar(); } 37 return x*t; 38 } 39 int c[N]; 40 int main() 41 { 42 int T=read(); 43 while(T--) 44 { 45 int n=read(); 46 for(int i=0;i<n;i++) 47 { 48 int x=read(); 49 c[((x+i)%n+n)%n]++; 50 } 51 int ans=0; 52 for(int i=0;i<n;i++) 53 if(c[i]==0){ 54 ans=1; 55 break; 56 } 57 for(int i=0;i<n;i++) c[i]=0; 58 if(ans) printf("NO\n"); 59 else printf("YES\n"); 60 } 61 return 0; 62 }
Codeforces Round #639 (Div. 2) C Hilbert's Hotel (数学)
原文:https://www.cnblogs.com/DeepJay/p/12861148.html