题目大意:一个骰子在有R*C格的矩形地图上从第一行第一格开始滚来滚去,滚完一行后以相反方向滚下一行,滚完所有格子后停。求所有时刻骰子上方的点数和。
O(RC)做法:模拟。用u,f,r分别记录骰子上、前、右三面的点数。
向左滚:int d=7-u;u=r;r=d;//骰子相对面上点数和为7,d暂存底面点数,滚动后原来的右面跑到上面,底面跑到右面。
向右滚:int l=7-r;r=u; u=l;//l暂存左面点数
向下滚:int b=7-f;f=u; u=b;//b暂存后面点数
O(1)做法:数学(找规律)。在同一行中,每滚4次一循环,这四次的顶面点数和为14。所以ans(r,c)=c/4*r*14+ans(r,c%4)。对于剩下的长条矩阵,仍然存在循环节,循环节长度只与c%4有关。所以可以先打出循环节,再统计。
#include<iostream> #include<cstdio> using namespace std; const int a[4][6]={{0,0,0,0,0,0},{0,1,6,12,14,0},{0,5,11,19,28,36},{0,11,0,0,0,0}}; const int b[4]={1,4,6,2}; const int c[4]={0,14,42,22}; int n,m,x,y,p,q; int main() { scanf("%d%d",&n,&m); x=m/4; y=m%4; p=n/b[y]; q=n%b[y]; printf("%lld",(long long)14*x*n+(long long)c[y]*p+(long long)a[y][q]); return 0; }