Codeforces 251C Number Transformation

Number Transformation

我们能发现这个东西是以2 - k的lcm作为一个循环节, 然后bfs就好啦。

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define PLL pair<LL, LL>
#define PLI pair<LL, int>
#define PII pair<int, int>
#define SZ(x) ((int)x.size())
#define ull unsigned long long

using namespace std;

const int N = 5e5 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-8;
const double PI = acos(-1);

LL a, b;
int k, lcm = 1;
int dp[N];

void getDp(int x) {
    memset(dp, -1, sizeof(dp));
    dp[x] = 0;
    queue<int> que;
    que.push(x);
    while(!que.empty()) {
        int u = que.front(); que.pop();
        if(dp[u - 1] == -1) {
            dp[u - 1] = dp[u] + 1;
            que.push(u - 1);
        }
        for(int i = 2; i <= k; i++) {
            int v = u - (u % i);
            if(~dp[v]) continue;
            dp[v] = dp[u] + 1;
            que.push(v);
        }
    }
}

int main() {
    scanf("%lld%lld%d", &a, &b, &k);
    swap(a, b);
    for(int i = 2; i <= k; i++)
        lcm = lcm / __gcd(lcm, i) * i;
    LL ans = 0;
    LL R = b - (b % lcm);
    LL L = a + (lcm - a % lcm) % lcm;
    if(L <= R) {
        LL cnt = (R - L) / lcm;
        getDp(lcm - 1);
        ans = dp[0] * cnt + cnt;
        if(a % lcm) ans += dp[a % lcm] + 1;
        getDp(b % lcm);
        ans += dp[0];
    } else {
        getDp(b % lcm);
        ans = dp[a % lcm];
    }
    printf("%lld\n", ans);
    return 0;
}

/*
*/

原文地址:https://www.cnblogs.com/CJLHY/p/10466476.html

时间: 2024-11-01 08:55:18

Codeforces 251C Number Transformation的相关文章

Codeforces 346C Number Transformation II 构造

题目链接:点击打开链接 = = 990+ms卡过 #include<stdio.h> #include<iostream> #include<string.h> #include<algorithm> #include<vector> #include<set> using namespace std; #define N 100010 #define L(x) (x<<1) #define R(x) (x<<

CodeForces 346C Number Transformation II

Number Transformation II 题解: 对于操作2来说, a - a % x[i] 就会到左边离a最近的x[i]的倍数. 也就是说 [ k * x[i] + 1,  (k+1)* x[i] -1 ]这段区间的的数都会走到 k * x[i]上. 所以对于每个位置都先计算出他到右边最远的覆盖位置. 然后在反着求出每个位置能往左走走到的最远的位置. 代码: #include<bits/stdc++.h> using namespace std; #define Fopen freo

codeforces 251C C. Number Transformation(数论+dp)

题目链接: codeforces 251C 题目大意: 给出两个数a,b,k有两种操作,a-=1,或者a-=a%x(2<=x<=k),问最少需要多少步操作能够使a变成b 题目分析: 首先我们考虑数据范围小的怎么做,定义状态dp[i]表示从a到达i最少需要多少步 {dp[i?1]=min(dp[i?1],dp[i]+1)dp[i?i%x]=min{(dp[i?i%x],dp[i]+1)|2≤x≤k} 那么我们考虑题目给出的数据范围好大,直接做肯定超时,那么考虑每步操作只有a-=1和a-=a%x,

HDU 4952 Number Transformation 多校8 机智数学

哎.这个题想了好久,状态不对啊...一个大家都出的题..当时想到肯定是可以有什么规律来暴力,不用算到10的10次方 对于某个k,x.从1到k循环,每次求一个新的x,这个x要大于等于原x,并且要是i的倍数... 一直觉得有规律可循,后来知道就是倍数,我们设倍数为 b, 则b2*(i+1)>=b1*(i);可以知道b2>=b1-b1/(i+1),则,b2在b1小于等于i+1的时候便不会再变换,题目最大的倍数为10的10次方,根据第一个式子,最多经过10的五次方,倍数就会缩为10的五次方,此时i也&

hdu 4952 Number Transformation (找规律)

题目链接 题意:给你个x,k次操作,对于第i次操作是:要找个nx,使得nx是>=x的最小值,且能整除i,求k次操作后的数 分析: 经过打表找规律,会发现最后的x/i,这个倍数会趋于一个固定的值,求出这个固定的值和K相乘就可以了, 为什么会趋于固定的值呢,因为最后虽然i在不断增长,但是x也是在增长的,每次的倍数会回退一个发现 有余数,然后再加上一个,所以趋于稳定. 官方题解: 1 #include <iostream> 2 #include <cstdio> 3 #includ

bzoj 3858: Number Transformation

3858: Number Transformation Time Limit: 1 Sec  Memory Limit: 64 MBSubmit: 82  Solved: 41[Submit][Status] 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 th

Codeforces 486C Palindrome Transformation(贪心)

题目链接:Codeforces 486C Palindrome Transformation 题目大意:给定一个字符串,长度N,指针位置P,问说最少花多少步将字符串变成回文串. 解题思路:其实只要是对称位置不相同的,那么指针肯定要先移动到这里,修改字符只需要考虑两种方向哪种更优即 可.然后将所有需要到达的位置跳出来,贪心处理. #include <cstdio> #include <cstring> #include <cstdlib> #include <vec

HDU-4952 Number Transformation

http://acm.hdu.edu.cn/showproblem.php?pid=4952 Number Transformation Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 171    Accepted Submission(s): 69 Problem Description Teacher Mai has an inte

HDU 4952 Number Transformation(公式)

HDU Number Transformation 题目链接 题意:按题目中要求求出最后的n 思路:推公式(i+1)x′>=ix,得到x′>=1+floor(xi+1),这样一来就可以递推x,那么注意题目中k很大,但是实际上如果i到一定数值之后,x就不会在增长了,这时候就可以break了 代码: #include <cstdio> #include <cstring> typedef long long ll; ll n, k; int main() { int cas