UVA-10710 Skyscraper Floors (找规律+幂取模)
题目大意:题目中给了一种数的定义,根据定义,让判断一个给定的数是不是这种数。题中叫这种数为吉米数,定义如下:对序列1,2,3,,,,n,做n-1次SF变换(对该变换的解释在下文),如果能得到原序列,则n为吉米数。
SF变换:若n为偶数,以n=10为例,一次SF变换是这样的
1,2,3,4,5,6,7,8,9,10—>1,2,3,4,5 6,7,8,9,10—>6,1,7,2,8,3,9,4,10,5 此为偶数的一次SF变换,第二次变换是基于新序列的,以此类推。
若n为奇数,以n=9为例,一次SF变换是这样的
1,2,3,4,5,6,7,8,9—>1,2,3,4 5,6,7,8,9—>5,1,6,2,7,3,8,4,9 此为奇数的一次SF变换,第二次变换也是基于新序列的,以此类推。
题目分析:根据题中的提示,偶数不是吉米数。如果是吉米数,则相应的序列中的任一元素的位置周期都是一样的,所以只需考虑1。最终找到1的位置有如下规律:pos=(2^t)%n,其中t为变换的次数。所以只需判断(2^(n-1))%n=1是否成立即可。
实际上还是幂取模!!!
代码如下:
1 # include<iostream> 2 # include<cstdio> 3 # include<cstring> 4 # include<algorithm> 5 using namespace std; 6 # define ll long long 7 ll mypow(ll a,ll b,ll m) 8 { 9 if(b==0) 10 return 1; 11 if(b==1) 12 return a%m; 13 ll u=mypow(a,b/2,m); 14 u*=u; 15 u%=m; 16 if(b&1) 17 u*=a; 18 return u%m; 19 } 20 bool is(ll x) 21 { 22 ll pos=mypow(2,x-1,x); 23 return pos==1; 24 } 25 int main() 26 { 27 ll n; 28 while(scanf("%lld",&n)&&n!=-1){ 29 if(is(n)) 30 printf("%lld is a Jimmy-number\n",n); 31 else 32 printf("%lld is not a Jimmy-number\n",n); 33 } 34 return 0; 35 }