题目大意:一个骰子在有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;
}