hdu4952 Number Transformation (找规律)
2014多校 第八题 1008
2014 Multi-University Training Contest 8
4952 | Number Transformation |
Number TransformationTime Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 85 Accepted Submission(s): 31 Problem Description
Teacher Mai has an integer x.
He does the following operations k times. In the i-th operation, x becomes the least integer no less than x, which is the multiple of i. He wants to know what is the number x now. Input
There are multiple test cases, terminated by a line "0
0".
For each test case, the only one line contains two integers x,k(1<=x<=10^10, 1<=k<=10^10). Output
For each test case, output one line "Case #k: x", where
k is the case number counting from 1.
Sample Input
2520 10
2520 20
0 0
Sample Output
Case #1: 2520
Case #2: 2600
Source
Recommend
hujie
|
大意:输入x和k,进行k次操作,每次把x变成大于等于x的最小的k的倍数,求最后的x。(1<=x k <=10^10)
题解:怒找规律。
这个的暴力做法很好写,几行就写出来了:
1 now=x; 2 for(i=1;i<=k;i++){ 3 mo=now%i; 4 if(mo!=0){ 5 now+=i-mo; 6 } 7 }
↑这个是比纯暴力优化了一点的,因为已知余数就可以直接算得下一个x,不用一个个加一个个试。
但是这样还是会超时得飞起来,10^10的数据必须找比O(n)小的方法。
于是我们可以在循环里面输出各种mo、i-mo、now之类的数,输入一点大数据观察一下有没有规律。
然后可以发现每次到后期,i-mo都会变成一个固定值!虽然我也不懂为什么,不过知道这个就可以了。当我们发现进入了这个状态时,直接now+=(不变的i-mo)*(k-i),得到最后结果。
于是我们统计i-mo连续多少次不变的次数,达到一定值就认为永远不变了,直接算。这个有时候也会出现连续5个不变之后又变了的,所以我设的是100次,多个100而已,对整体影响很小。
1 ll farm(ll x,ll k) { 2 ll i,now,mo; 3 ll pre,cnt,maxc=100; 4 pre=-1; 5 cnt=1; 6 now=x; 7 for(i=1; i<=k; i++) { 8 mo=now%i; 9 if(mo!=0) { 10 now+=i-mo; 11 } 12 if(cnt>=maxc) { 13 now+=pre*(k-i); 14 break; 15 } 16 if(i-mo==pre)cnt++; 17 else cnt=1; 18 pre=i-mo; 19 } 20 return now; 21 }
全代码:
1 //#pragma comment(linker, "/STACK:102400000,102400000") 2 #include<cstdio> 3 #include<cmath> 4 #include<iostream> 5 #include<cstring> 6 #include<algorithm> 7 #include<cmath> 8 #include<map> 9 #include<set> 10 #include<stack> 11 #include<queue> 12 using namespace std; 13 #define ll long long 14 #define usint unsigned int 15 #define mz(array) memset(array, 0, sizeof(array)) 16 #define minf(array) memset(array, 0x3f, sizeof(array)) 17 #define REP(i,n) for(i=0;i<(n);i++) 18 #define FOR(i,x,n) for(i=(x);i<=(n);i++) 19 #define RD(x) scanf("%d",&x) 20 #define RD2(x,y) scanf("%d%d",&x,&y) 21 #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z) 22 #define WN(x) printf("%d\n",x); 23 #define RE freopen("D.in","r",stdin) 24 #define WE freopen("1biao.out","w",stdout) 25 26 ll farm(ll x,ll k) { 27 ll i,now,mo; 28 ll pre,cnt,maxc=100; 29 pre=-1; 30 cnt=1; 31 now=x; 32 for(i=1; i<=k; i++) { 33 mo=now%i; 34 if(mo!=0) { 35 now+=i-mo; 36 } 37 if(cnt>=maxc) { 38 now+=pre*(k-i); 39 break; 40 } 41 if(i-mo==pre)cnt++; 42 else cnt=1; 43 pre=i-mo; 44 } 45 return now; 46 } 47 48 int main() { 49 int cas=1, ans; 50 ll x,k,now,i,mo,pre,ppre,flag; 51 while(scanf("%I64d%I64d",&x,&k)!=EOF) { 52 if(x==0 && k==0)break; 53 printf("Case #%d: %I64d\n",cas++,farm(x,k)); 54 } 55 return 0; 56 }