题意:一共有n排同学每排同学有m个人, 老师问问题有一个顺序, 先从第一排开始问,问完第一排的所有同学之后,再问第2排的,对于所有排的访问顺序为 1,2,3……n-1,n,n-1,n-2,……,2,1,2,然后每次访问到新的一排先要问完这一排的所有人才会往下一(目标)排走。
题解:先声明我们开一个数组来记录这一排被询问的总次数,先将k /= m, 这个代表的是完全访问的次数,即一整排m位同学都问完有几次,如果 完全访问的次数< n, 我们就将前几排全访问次数的人都加上m,并且将剩下的访问次数都塞到一下排就好了,如果完全访问次数大于n了之后,发现除了第一次转移的次数位n-1排, 我们再对 k/=(n-1) 处理出来, 然后判断奇偶性来决定最后一次是从上到下还是从下到上,对于所有的排都加上次数,最后再把刚开始的访问次数塞到目标排就好了。
n==1的话,对于上述解法要特殊讨论因为除数或者模数不能为0。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout); 4 #define LL long long 5 #define ULL unsigned LL 6 #define fi first 7 #define se second 8 #define pb push_back 9 #define lson l,m,rt<<1 10 #define rson m+1,r,rt<<1|1 11 #define max3(a,b,c) max(a,max(b,c)) 12 #define min3(a,b,c) min(a,min(b,c)) 13 typedef pair<int,int> pll; 14 const LL INF = 0x3f3f3f3f3f3f3f3f; 15 const LL mod = (int)1e9+7; 16 const int N = 2e5 + 100; 17 LL n, m, x, y; 18 LL k, ans1, ans2 = INF, ans3; 19 LL cnt[N]; 20 int main(){ 21 scanf("%I64d%I64d%I64d%I64d%I64d", &n, &m, &k, &x, &y); 22 LL c1, c2; 23 c1 = k/m; 24 c2 = k%m; 25 swap(c1, k); 26 if(k < n){ 27 for(int i = 1; i <= k; i++) cnt[i] = m; 28 cnt[k+1] = c2; 29 } 30 else { 31 for(int i = 1; i <= n; i++) cnt[i] = m; 32 k -= n; 33 if(n != 1){ 34 LL t = n-1; 35 LL z = k / t; 36 LL lf = k % t; 37 LL t1 = z-z/2; 38 for(int i = 1; i < n; i++) cnt[i] += t1*m; 39 for(int i = 2; i <= n; i++) cnt[i] += z/2 * m; 40 if(z&1ll){ 41 int g = 1; 42 for(int i = 2; i <= n, lf > 0; i++, lf--) cnt[i] += m, g = i; 43 cnt[++g] += c2; 44 } 45 else{ 46 int g = n; 47 for(int i = n-1; i >= 1, lf > 0; i--, lf--) cnt[i] += m, g = i; 48 cnt[--g] += c2; 49 } 50 } 51 else cnt[1] = c1; 52 } 53 for(int i = 1; i <= n; i++){ 54 if(cnt[i] == 0) {ans2 = 0; continue;} 55 if(i == x) { 56 LL lf = cnt[i]%m; 57 ans3 = cnt[i]/m; 58 if(lf >= y) ans3++; 59 }; 60 LL t1 = cnt[i]/m; 61 if(cnt[i]%m) t1++; 62 ans1 = max(ans1, t1); 63 LL t2 = cnt[i]/m; 64 ans2 = min(ans2, t2); 65 } 66 67 printf("%I64d %I64d %I64d", ans1, ans2, ans3); 68 return 0; 69 }