hdu4952 Number Transformation (找规律)

2014多校 第八题 1008

2014 Multi-University Training Contest 8

4952 Number Transformation

Number Transformation

Time 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 }
View Code

 

转载于:https://www.cnblogs.com/yuiffy/p/3913186.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值