题目大意
详细题目传送门
在这个立方体中,两个对立面的点数之和等于 \(7\)。将立方体放在了一个 \(r\times c\) 的矩阵的左上方,最初立方体的方向是上侧显示 \(1\),右侧显示 \(3\)。次重复以下动作:
- 向右滚动立方体,直到它到达最后一列;
- 向下滚动到下一行;
- 向左滚动立方体,直到它到达第一列;
- 像第二步一样,向下滚动到下一行。
求滚动到不能滚动时所有位置的点数每一步的上方点数之和。
\(1\leqslant r,c\leqslant 10^5\)。
思路
显然正确答案是要求枚举一行,然后直接求出每一列的情况的。发现维护一个骰子的上右前三面就可以快速求出每一次翻转的情况。然后发现有循环,\(4\) 次为一组。每一次循环的和固定为 \(14\)。所以暴力维护 \(c \bmod4\) 次右/左滚操作即可。
然后上下也一样。对于上右前三面的变换可以自己推。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll up=1,rt=3,ft=2,ans=0;
ll tr(){ll Up=7-rt;rt=up;up=Up;return up;
}
ll tl(){ll Up=rt;rt=7-up;up=Up;return up;
}
int main(){ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);ll r,c;cin>>r>>c;c--;for(int i=1;i<=r;++i){ll Ans=ans;ans+=up;ans+=14*(c/4);for(int j=1;j<=c%4;++j){if(i&1){ans+=tr();}else{ans+=tl();}}ll Ft=ft;ft=up;up=7-Ft;}cout<<ans<<endl;return 0;
}