题目
1337个人排成一个圈,从1号人开始报数,初始方向是1,2,3…。如果某个人报的数是7的倍数或数字中含有7,那么报数的方向就反一下。问报数字X的是哪个人?
题解
间接打表
没想到打表也成正解了hhh。
能全打没问题,间接打是一个新方法。因为10^8以内可以轻松解决,只要把10^9的那个给压缩成10^8级别就好了。
那么可以考虑打出k*10^8的表。对于x,从0暴力求到x%1e8,初始状态为x/1e8。
在加1的细节上可以用逐位加的方法,提高效率。
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int p[]={0,548,866,892,64,1303,97,1278,1278,960,934};
int d[]={1,1,-1,-1,1,1,-1,1,-1,1,1};
/*inline bool check(int x)
{
while(x)
{
if(x%10==7) return true;
x/=10;
}
return false;
}*/
int c,a[20];
void init(int x)
{
c=0;int len=0;
while(x)
{
a[len]=x%10;x/=10;
if(a[len]==7) c++;
}
}
inline void add(int l)
{
a[l]++;
if(a[l]==7) c++;
else if(a[l]==8) c--;
else if(a[l]==10) a[l]=0,add(l+1);
}
int main()
{
int n;scanf("%d",&n);
int first=n/(int)1e8,t=first*(int)1e8;
int x=p[first],dir=d[first];
init(t);
for(int i=t+1;i<=n;i++)//debug i=t
{
add(1);
x+=dir;//debug 先到这才转方向
if(c || i%7==0) dir=-dir;
if(!x) x=1337;else if(x==1338) x=1;
}
printf("%d\n",x);
return 0;
}