Codeforces 758C:Unfair Poll(思维+模拟)

http://codeforces.com/problemset/problem/758/C

题意:教室里有n列m排,老师上课点名从第一列第一排开始往后点,直到点到第一列第m排,就从第二列第一排开始点,当点完第n列的名之后,接着点第n-1列的名。以此类推,就是从列上来看的话:1,2,3,4,……,n,n-1,n-2,……,1 ,2,……。这样的顺序点名。老师上课总共点k次名,问该课堂最多可以点同一个同学多少次,最少可以点同一个同学多少次,点了位置为(x,y)的同学多少次名。

思路:一遇到这种题目就有点血崩。确信以为是一条公式可以做出来的题目,然后写了一页草稿纸,连样例都过不了,不知所措。赛后想看看别人的公式,结果看过的都是通过计算+模拟的。既然用计算机了,在符合时间复杂度的情况下用模拟帮助计算,好像没什么问题啊。(为什么我就直接确信直接去推公式了,而且好像也不是第一次犯这种错误了啊)。

首先要注意点名的列顺序,好像挺多人都没看懂题目(就算我看懂了然并卵),假设n是4,那么顺序是1,2,3,4,3,2,1,2,3,……。这样的,所以从列来看一个周期是(n+n-2),因为当n = 1的时候这条式子等于0,所以要特判n = 1的情况。如果n = 1的话,那么每次都是点这一排了,最多的人是算了k / m次,剩下的用k % m从第一排去模拟加上,直到那个余数变成0为止。如果n > 1的话,那么每个周期点第1列和第n列的次数是只有一次,而点2~n-1列的次数是有两次,那么可以点的周期数 = k / m / (n+n-2),然后剩下的用k % (m * (n+n-2))去模拟。因为初始是从第一列开始的,所以从第一列开始扫起。

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <cstring>
 5 #include <string>
 6 #include <cmath>
 7 #include <queue>
 8 #include <vector>
 9 #include <map>
10 #include <set>
11 #include <stack>
12 using namespace std;
13 #define INF 0x3f3f3f3f
14 #define N 100010
15 typedef long long LL;
16 LL mp[105][105];
17
18 int main() {
19     int x, y, n, m;
20     LL k;
21     cin >> n >> m >> k >> x >> y;
22     LL mi = -1, ma = -1;
23     if(n == 1) {
24         LL yu = k % m;
25         LL cnt = k / m;
26         for(int i = 1; i <= m; i++) mp[1][i] += cnt;
27         for(int i = 1; i <= m; i++)
28             if(yu) mp[1][i]++, yu--;
29     } else {
30         LL num = (n + n - 2) * m;
31         LL cnt = k / num; // 周期数
32         LL yu = k % num;
33         for(int i = 1; i <= n; i++)
34             for(int j = 1; j <= m; j++)
35                 if(i == 1 || i == n) mp[i][j] += cnt;
36                 else mp[i][j] += cnt * 2;
37         for(int i = 1; i <= n; i++)
38             for(int j = 1; j <= m; j++)
39                 if(yu) mp[i][j]++, yu--;
40         for(int i = n - 1; i >= 1; i--)
41             for(int j = 1; j <= m; j++)
42                 if(yu) mp[i][j]++, yu--;
43     }
44     for(int i = 1; i <= n; i++) {
45         for(int j = 1; j <= m; j++) {
46             if(ma < mp[i][j]) ma = mp[i][j];
47             if(mi == -1 || mi > mp[i][j]) mi = mp[i][j];
48         }
49     }
50     printf("%I64d %I64d %I64d\n", ma, mi, mp[x][y]);
51     return 0;
52 }
时间: 2024-08-06 17:11:33

Codeforces 758C:Unfair Poll(思维+模拟)的相关文章

Codeforces 392 C Unfair Poll(模拟)

题意:老师点名顺序规则如下:第1排,第2排,--,第n-1排,第n排,第n-1排,--,第2排,第1排,第2排,--,第n-1排,第n排,--对于每排都是从左到右依次点名,问点名k个人后,所有人中最多的点名次数,最少的点名次数,以及位于x排y列处的同学的点名次数. 分析: 1.由于k很大,将第1排,第2排,--,第n-1排,第n排,第n-1排,--,第2排看成一个循环. 2.这个循环中有2*(n-1)*m个人,注意当n=1时,这个循环中有m个人,将这个循环人数记为tmp. 3.利用k/tmp,算

CodeFroces 758C - Unfair Poll

题意: 老师点名,顺序是1 -- n -- 1 排为一个循环,每列为1 -- m的顺序, 问点到最多次数和最少次数的人的次数以及(x,y)被点的次数. 分析: 由于点名有循环,故可先判断出每一个循环每个人被点名的次数,再乘以循环数,为答案一部分. 最后一个循环结束后k还有余数,从(1,1)暴力模拟,因为n*m才10000, 再加上前面的,就能得出答案. 注意 n=1 需要特判. 1 #include <bits/stdc++.h> 2 using namespace std; 3 #defin

CodeForces 758 C Unfair Poll

Unfair Poll 题意:一共有n排同学每排同学有m个人, 老师问问题有一个顺序, 先从第一排开始问,问完第一排的所有同学之后,再问第2排的,对于所有排的访问顺序为 1,2,3--n-1,n,n-1,n-2,--,2,1,2,然后每次访问到新的一排先要问完这一排的所有人才会往下一(目标)排走. 题解:先声明我们开一个数组来记录这一排被询问的总次数,先将k  /= m, 这个代表的是完全访问的次数,即一整排m位同学都问完有几次,如果  完全访问的次数< n, 我们就将前几排全访问次数的人都加上

codeforces 758C

codeforces 758C C. Unfair Poll introduction 一个矩形方格,从前到后,再从后到前数k次,问每个方格最多/最少经过多少次,(x,y)方格上经过多少次 method 遍历是有周期的,一个周期经过2(n-1)m个方格,当n=1时,周期为m 先求出周期,再求出剩下的次数,然后将剩下的次数,通过遍历分配到每一个方格上 tips o(1)解决问题比较困难的时候,可以向o(n)求助 Q&A conclusion 想到了周期性,但是没有处理好外层循环和内层循环的关系,

Codeforces 475C Kamal-ol-molk&#39;s Painting 模拟

题目链接:点击打开链接 题意:给定n*m的矩阵 X代表有色 .代表无色 用一个x*y的矩阵形刷子去涂色. 刷子每次可以→或↓移动任意步. 若能够染出给定的矩阵,则输出最小的刷子的面积 若不能输出-1 思路: 先找到连续最小的x,y 因为至少一个边界和x或y相等,所以枚举(x,i) 和 (i,y)就可以了. #pragma comment(linker, "/STACK:102400000,102400000") #include <stdio.h> #include <

Codeforces 30D King&#39;s Problem? 模拟

首先将n个点排序,找出排序后的K,然后分情况讨论. 当 k == n+1时,显然是 k->1->n || k->n->1这两种的较小值,因为三角形的两边之和大于第三边. 当1 <= k && k <= n 时: 1 , k -> 1 -> n+1 -> k+1 ->n  ||  k -> n -> n+1 -> k-1 -> 1,当k+1 || k-1 不存在时将对应步骤忽略. 2 , k - > 1

Codeforces Round #399 B 思维 C 模拟 D 概率dp E SG博弈

Divide by Zero 2017 and Codeforces Round #399 (Div. 1 + Div. 2, combined)B. Code For 1 题意:数n,不断拆分为 n/2, n&1, n/2,直到都为0或1.求区间[l, r]有多少个1. tags:画一画很容易看出来,类似dfs中序遍历. //#399 B #include<bits/stdc++.h> using namespace std; #pragma comment(linker, &quo

Codeforces 950D A Leapfrog in the Array ( 思维 &amp;&amp; 模拟 )

题意 : 给出 N 表示有标号 1~N 的 N 个数,然后从下标 1 开始将这 N 个数每隔一位放置一个,直到 N 个数被安排完,现在有一个操作就是每次将数列中最右边的数向离其左边最近的空缺处填上,一直这样子填,直到下标 1~N 被填满,然后现在给出 Q 个询问,每个询问给出一个 X ,你需要回答下标为 X 的位置填放了什么数? 分析 :   初始状态每个数都处于奇数位,且可以根据位置下标得到具体的数是什么,即 num = (pos>>1)  + 1 观察到当最后填充操作完成时,每个奇数位置的

【CodeForces 915 C】Permute Digits(思维+模拟)

You are given two positive integer numbers a and b. Permute (change order) of the digits of a to construct maximal number not exceeding b. No number in input and/or output can start with the digit 0. It is allowed to leave a as it is. Input The first