题面

题解

毒瘤题浪费我大好青春

容易知道, 如果\(l\)和\(r\)位数不一样, 直接选形似\(99..99\)的数, 输出答案即可

\(l\)和\(r\)位数一样的话, 当位数确定的时候, 由于已知\(p\), 所以每一位要跟\(k\)中哪些位相乘已经确定了

设\(f[i]\)为\(k\)中与\(x\)中第\(i\)位相乘的数的和

首先, 每\(lcm(lenx, lenk)\)一个周期, 这个直接暴力算即可

//考虑到x中mod d(lenx与lenk的gcd)同余的数在一个周期内f相等(自己举几个特例, 我不会证)
//故只用枚举mod d的余数即可, 然后模拟选的过程
//假设这个数这一次被选是t时间, p位置, 那么它下一次被选就是(t + lenx)时间, (p + lenx)%lenk位置, 由于我的数组是从1开始, 所以是(p + lenx - 1)%lenk + 1
//然后由于1~lenk中每个数只会被一个i跳到(自己画图, 或者感性理解一下:如果跳到了说明这个周期会更小, 矛盾)
//给每个数标记他被i所跳到的时间(这个等会会用到) 也就是pos, 再给每个位置标记上他被i跳到时累加的值, 也就是sum
for(int i = 0; i < d; i++)
{
int num = 0, poss = 1, j = i + 1;
do
{
num += k[j];
pos[j] = poss;
sum[j] = num;
++poss;
j = ((j + l[0] - 1) % k[0] + k[0]) % k[0] + 1;
}
while(j != i + 1);
g[i] = num;
}

这样就可以计算出整个周期的\(f[]\)的值, 然后我们看怎么计算不是整周期的\(f[]\)的值

由于每个位置跳了多少次是可以算出来的, 所以我们可以算出来它最后在哪一个位置

然后用终点的\(sum\)减去起点的\(sum\)即可

但是有一个细节, 就是当终点的\(pos\)小于等于起点的\(pos\)时, 它要加上一个\(g[i \% d]\), 根据图理解一下吧, 我讲不清

这个图太小了吧...

算了, 蓝色点是终点, 绿色点是起点, 可以知道起点到终点是那条红色路径, 然后你如果用终点的\(sum\)减去起点的\(sum\)就是负的绿色的那条, 加上一个\(g[i \% d]\)就是那条红色的了

最后讲一下统计答案

考虑贪心

对于一个数x, 它的前\(i\)位跟\(r\)一样, 第\(i + 1\)位小于\(r[i + 1]\), 后面的都是9, 这样必定是最优的, 从后往前不断更改这个\(i + 1\)的位置即可

Code

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#define itn int
#define reaD read
#define N 100005
#define int long long
using namespace std; int l[N], r[N], k[N], pos[N];
long long p, res1, res2, ans, g[N], sum[N], f[N]; template < typename T >
inline T read()
{
T x = 0, w = 1; char c = getchar();
while(c < '0' || c > '9') { if (c == '-') w = -1; c = getchar(); }
while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
return x * w;
} int gcd(int m, int n) { return !n ? m : gcd(n, m % n); } signed main()
{
char c = getchar();
while(c < '0' || c > '9') c = getchar();
while(c >= '0' && c <= '9') l[++l[0]] = c - '0', c = getchar();
while(c < '0' || c > '9') c = getchar();
while(c >= '0' && c <= '9') r[++r[0]] = c - '0', c = getchar();
while(c < '0' || c > '9') c = getchar();
while(c >= '0' && c <= '9') k[++k[0]] = c - '0', c = getchar();
p = read <long long> ();
if(l[0] < r[0])
{
int r = p % k[0], q = p / k[0];
for(int i = 1; i <= k[0]; i++)
ans += k[i] * (q + (i <= r)) * 9;
printf("%lld\n", ans); return 0;
}
int d = gcd(l[0], k[0]);
for(int i = 0; i < d; i++)
{
int num = 0, poss = 1, j = i + 1;
do
{
num += k[j];
pos[j] = poss;
sum[j] = num;
++poss;
j = ((j + l[0] - 1) % k[0] + k[0]) % k[0] + 1;
}
while(j != i + 1);
g[i] = num;
}
int q = p / (l[0] * k[0] / d), x = p % (l[0] * k[0] / d), w = x / l[0], y = x % l[0];
for(int i = 1; i <= l[0]; i++)
{
f[i] = g[((i - 1) % d + d) % d] * q;
int cnt = w + (i <= y);
if(!cnt) continue;
int lst = ((i - l[0] - 1) % k[0] + k[0]) % k[0] + 1, nxt = ((i + (cnt - 1) * l[0] - 1) % k[0] + k[0]) % k[0] + 1;
f[i] += sum[nxt] - sum[lst] + (pos[nxt] <= pos[lst] ? g[((i - 1) % d + d) % d] : 0);
}
int top = 1;
while(top <= l[0] && l[top] == r[top]) top++;
for(int i = 1; i <= l[0]; i++)
res1 += r[i] * f[i];
ans = res1; res1 -= f[l[0]];
for(int i = l[0]; i >= top + 1; i--)
{
res1 += (10 - r[i]) * f[i];
res1 -= f[i - 1];
ans = max(ans, res1);
}
printf("%lld\n", ans);
return 0;
}

[51nod1666] 最大值的更多相关文章

  1. C语言 · 最大值与最小值计算

    输入11个整数,计算它们的最大值和最小值. 样例输入 0 1 2 3 4 5 6 7 8 9 10 样例输出 10 0   #include<stdio.h> int main(){ ]; ...

  2. [LeetCode] Split Array Largest Sum 分割数组的最大值

    Given an array which consists of non-negative integers and an integer m, you can split the array int ...

  3. [LeetCode] Sliding Window Maximum 滑动窗口最大值

    Given an array nums, there is a sliding window of size k which is moving from the very left of the a ...

  4. 整理:Javascript获取数组中的最大值和最小值的方法汇总

    方法一: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 //最小值 Array.prototype.min = function ...

  5. HDU 1754 I Hate It 线段树单点更新求最大值

    题目链接 线段树入门题,线段树单点更新求最大值问题. #include <iostream> #include <cstdio> #include <cmath> ...

  6. Poj The xor-longest Path 经典题 Trie求n个数中任意两个异或最大值

    Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 5646   Accepted: 1226 Description In an ...

  7. 不需要sql进行计算数据的平均值、最大值、最小值、和

    介绍下SqlServer.前端js.后台C#三个阶段对均值.最大值.最小值.和计算int[] jisuan = {0, 1, 3, 5, 7,8 }; List<int> jisuan2 ...

  8. 在一个SQL Server表中的多个列找出最大值

    在一个SQL Server表中一行的多个列找出最大值 有时候我们需要从多个相同的列里(这些列的数据类型相同)找出最大的那个值,并显示 这里给出一个例子 IF (OBJECT_ID('tempdb..# ...

  9. C语言 · 寻找数组中的最大值

    问题描述 对于给定整数数组a[],寻找其中最大值,并返回下标. 输入格式 整数数组a[],数组元素个数小于1等于100.输出数据分作两行:第一行只有一个数,表示数组元素个数:第二行为数组的各个元素. ...

随机推荐

  1. hdu 2846 字典树变形

    mark: 题目有字串匹配的过程 有两点 1.为了高效的匹配子串 可以把所有的子串都预处理进去 然后字典树计数就放在最后面 2.在同一个母串处理自串的时候 会有重复的时候 比如abab  这里去重用个 ...

  2. axios 跨域携带cookie设置

    import axios from 'axios' // 创建axios实例 const service = axios.create({ baseURL: process.env.BASE_API, ...

  3. mvc 登陆界面+后台代码

    上代码 前端+js(懒得分文件了) @{ ViewBag.Title = "MVC权限系统架构学习-登录"; Layout = "/Views/Shared/_LoadJ ...

  4. 史上最全Java集合中List,Set以及Map等集合体系详解

    一.概述 List , Set, Map都是接口,前两个继承至collection接口,Map为独立接口 Set下有HashSet,LinkedHashSet,TreeSet List下有ArrayL ...

  5. react用高阶组件实现路由守卫

    react-router不像vue-router一样有很多钩子函数,可以做路由守卫.想实现路由守卫,可以用高阶组件来实现. @connect(state => ({ isLogin: state ...

  6. 小知识:修改IDEA的模板

    小知识:修改IDEA的模板 有时候我们会发现,IDEA默认创建的模板并不是我们常用的.与其每次都在创建后进行修改,不如直接对模板进行修改. 给不知道怎么修改的同学指一下路: File->sett ...

  7. 嵌入式安装telnet

    busybox配置 Defined at networking/Config.in:784 Depends on: TELNET Location: -> Networking Utilitie ...

  8. 不显示Zetero导出的文献库中的部分内容

    不显示Zetero导出的文献库中的部分内容 Zetero作为文献管理软件,收集到的参考文献的相关信息(域fields)比较齐全.文章或书籍的引用中仅仅只用到了其中的一部分,如作者.发表年.题名.期刊( ...

  9. String s=new String("xyz");创建了几个String Object?二者之前的区别是什么?

    两个.第一个对象是字符串常量"xyz",第二个对象是new String("xyz")的时候产生的,在堆中分配内存给这个对象,只不过这个对象的内容是指向字符串常 ...

  10. 404boom 博客闪现【不断的优化更新中。。。】

    404boom 博客闪现[不断的优化更新中...] 停止本篇博文EQ继续优化,所有博文将会在标签[cnblogs_v2 ]中重新整理,待完成统一放上链接 一:Java SE相关1.Java的概述2.J ...