CodeForces 758C Unfair Poll 模拟

题意:

教师有n行m列 一个老师点名

她会点k次 这个人坐在x行y列的位置

点名方法是从1~n 再从n-1~1

问 被点名次数最多的人被点了多少次 被点名次数最少的人被点了多少次 这个人被点了多少次

思路:

我们将从 1~n 再从 n-1~2 设为一个周期

这样每次新开始点第一排都意味着一个周期的开始

那么 我们一个周期就是点 n*m -2*m 次名

减去的是第一排和最后一排少点的次数

用k减去所有的整数周期 最后一个周期模拟一遍就好了

又是一道会爆int的题

原来cerr不影响AC= =

 1 #include<bits/stdc++.h>
 2 #define cl(a,b) memset(a,b,sizeof(a))
 3 #define debug(a) cerr<<#a<<"=="<<a<<endl
 4 using namespace std;
 5 typedef long long ll;
 6 typedef pair<int,int> pii;
 7 
 8 const int maxn=100+10;
 9 
10 ll seat[maxn][maxn];
11 
12 int main()
13 {
14     ll k,n,m,x,y;
15     cin>>n>>m>>k>>x>>y;
16     if(n==1)
17     {//n==1的情况可以直接算出来 n==2也是可以的
18         printf("%lld %lld %lld
",k/m+(k%m!=0),k/m,k/m+(y<k%m+1));
19         return 0;
20     }
21     ll turn=2*n*m-2*m;//每个周期点名的次数
22     int dir=1;//点名方向
23     int a=1,b=1,sum=k%turn;
24     ll l=(k/turn);
25     ll maximum=0,minimum=k/turn,he=0;
26     //计算每一个座位被点到的次数
27     for(int i=1;i<=n;i++)
28     {
29         for(int j=1;j<=m;j++)
30         {//最后一排和第一排是其他地方的一半次数
31             if(i==1 || i==n) seat[i][j]=k/turn;
32             else seat[i][j]=k/turn*2;
33         }
34     }
35     while(sum>0)
36     {//模拟最后一次不完整的周期
37         seat[a][b]++;
38         b++;
39         if(b>m) a+=dir,b=1;
40         if(a>n)
41         {//进入了一个周期的后半部分
42             a=n-1;
43             dir=-1;
44         }
45         sum--;
46     }
47     maximum=max(seat[1][1],max(seat[2][1],seat[n-1][1]));
48     //如果dir==-1 代表进入了一个点名周期的后半部分 最小值要+1
49     printf("%lld %lld %lld
",maximum,minimum+(dir==-1),seat[x][y]);
50     return 0;
51 }/*
52 
53 100 100 1000000000000000000 100 100
54 
55 */
原文地址:https://www.cnblogs.com/general10/p/7214459.html