【数位DP】CF 54C,509C,431D,628D,855E,1245F,95D

这一次有题解了!!

  • T1:CF54C First Digit Law
    • title
    • solution
    • code
  • T2:CF509C Sums of Digits
    • title
    • solution
    • code
  • T3:CF431D Random Task
    • title
    • solution
    • code
  • T4:CF628D Magic Numbers
    • title
    • solution
    • code
  • T5:CF855E Salazar Slytherin's Locket
    • title
    • solution
    • code
  • T6:CF1245F Daniel and Spring Cleaning
    • title
    • solution
    • code
  • T7:CF95D Horse Races
    • title
    • code

T1:CF54C First Digit Law

title

solution

这个题目是真的绕!!
其次本题是数位dpdpdp,概率dpdpdp,背包的结合
在这里插入图片描述
对于数位dpdpdp板块,其实我是没有写的,因为用简单的组合数就可以代替,显然

如果这个数长成1∗∗∗∗∗∗1******1,那么如果位数小于这个数的就是可以乱填出111的,
然后再加上1000000−1∗∗∗∗∗∗1000000-1******10000001中的个数就好了

如果这个数长成(>1)∗∗∗∗∗∗(>1)******(>1),那只要位数小于等于这个数都可以乱填

然后以取的区间个数作为重量,概率作为价值,乘号转移,然后自己领悟吧
在这里插入图片描述

code

#include <cstdio>
#define ll long long
int n, k;
double dp[1100], p[1100];ll solve( ll num ) {ll cnt = 0, last = 0, Pow = 1, ans = 0, x = num;while( x ) {last = x % 10;cnt ++;x /= 10;}for( int i = 1;i < cnt;i ++, Pow *= 10 )ans += Pow;if( last > 1 ) ans += Pow;else if( last == 1 ) ans += num - Pow + 1;return ans;
}int main() {scanf( "%d", &n );for( int i = 1;i <= n;i ++ ) {ll l, r;scanf( "%I64d %I64d", &l, &r );ll temp = solve( r ) - solve( l - 1 );p[i] = temp * 1.0 / ( r - l + 1 );}scanf( "%d", &k );dp[0] = 1.0;for( int i = 1;i <= n;i ++ )for( int j = n;~ j;j -- ) {dp[j] = dp[j] * ( 1 - p[i] );if( j > 0 ) dp[j] += dp[j - 1] * p[i];}double ans = 0;for( int i = 0;i <= n;i ++ )if( i * 100 >= n * k )ans += dp[i];printf( "%.12lf", ans );return 0;
}

T2:CF509C Sums of Digits

title

solution

我们想一下怎么才能构造出最小的?显然
从低到高位开始填,一直填999,到首位的时候就填剩下的那个数rrr
因为数的大小首先是位数,其次是位数上的值


第一个数肯定这样构造出来最小
接下来我们考虑后续数怎么构造出来
只有三种填法

①:仿照第一个数,也是后面全填999,首位填剩的
②:在前一个构造出来的数上的首位+1+1+1,这样保证大于后,后面就乱填
③:在前一个构造出来的数上的任意一位增加至999,直到满足数位和相等才停
显然,从低位往高位填是最小的
在这里插入图片描述

code

#include <cstdio>
int n, len;
int b[400], a[400];void solve( int num ) {for( int i = 1;num;i ++ ) {while( a[i] < 9 && num )a[i] ++, num --;if( i > len && ! num ) len = i;}
}void print() {for( int i = len;i;i -- )printf( "%d", a[i] );printf( "\n" );
}int main() {scanf( "%d", &n );for( int i = 1;i <= n;i ++ )scanf( "%d", &b[i] );solve( b[1] );print();for( int i = 2;i <= n;i ++ ) {int temp = b[i] - b[i - 1];if( temp > 0 ) {solve( temp );print();}else {int k = 1;while( 1 ) {if( k > len ) len = k;if( a[k] < 9 && temp > 0 ) {a[k] ++;solve( temp - 1 );print();break;}temp += a[k];a[k] = 0;k ++;}}}return 0;
}

T3:CF431D Random Task

title

solution

首先看nnn的范围[1,1e18][1,1e18][1,1e18]我们想要把这个降下来,唯一支持的时间复杂度就是logNlogNlogN
自然而然就会想到去二分答案nnn
但是二分必须要保证单调性,现在我们来证明一下n越大,二进制中有k个1的个数一定变大或不变

假设当前二分的答案为nnn
那么计算范围就是[n+1,2n][n+1,2n][n+1,2n]
对于n+1n+1n+1而言,我们主观是认为n+1n+1n+1一定不劣于nnn,有时候我们的主观是正确的
n+1n+1n+1计算范围为[n+2,2n+2][n+2,2n+2][n+2,2n+2]

分别把区间划分一下
[n+1,2n]=n+1,[n+2,2n][n+1,2n]=n+1,[n+2, 2n][n+1,2n]=n+1,[n+2,2n]
[n+2,2n+2]=[n+2,2n],2n+1,2n+2[n+2,2n+2]=[n+2,2n],2n+1,2n+2[n+2,2n+2]=[n+2,2n],2n+1,2n+2
发现[n+2,2n][n+2,2n][n+2,2n]可以抵消
n+1,2n+2n+1,2n+2n+1,2n+2也可以抵消!!
在这里插入图片描述
这个时候巧妙转化为二进制思考
在这里插入图片描述
2n+22n+22n+2n+1n+1n+1两倍,也就相当于2n+2=(n+1)<<12n+2=(n+1)<<12n+2=(n+1)<<1
二进制左移以为不就相当补了一个000,那么前面两个数中二进制含有111的个数是不变的!!
所以也可以抵消

此时[n+1,2n+2][n+1,2n+2][n+1,2n+2]就还剩下一个2n+12n+12n+1,所以一定不劣于,证毕
在这里插入图片描述
所以为什么题目是[n+1,2n][n+1,2n][n+1,2n]范围,如果是[n,2n][n,2n][n,2n]就不好说了,而且要求必须恰好为mmm不能大于


好了接下来,就是普通的数位dpdpdp了,先把套路搞起来
[l,r][l,r][l,r]转化为[1,r]−[1,l−1][1,r]-[1,l-1][1,r][1,l1]
然后用二进制数位dpdpdp
就是控制前iii位相等,然后后面乱填,这里不再赘述(你看代码就会马上get)
在这里插入图片描述

code

#include <cstdio>
#include <cstring>
#define ll long long
ll m;
int k, num[100];
ll dp[100][100];ll dfs( int pos, int sum, bool lim ) {if( ! pos ) return ( sum == k );if( ! lim && dp[pos][sum] != -1 ) return dp[pos][sum];int up = lim ? num[pos] : 1;ll ans = 0;for( int i = 0;i <= up;i ++ ) if( sum + ( i == 1 ) <= k )ans += dfs( pos - 1, sum + ( i == 1 ), lim && ( i == up ) );if( ! lim ) dp[pos][sum] = ans;return ans;
}ll solve( ll x ) {int len = 0;while( x ) num[++ len] = x & 1, x >>= 1;return dfs( len, 0, 1 );
}ll calc( ll x ) {return solve( x << 1 ) - solve( x );
}int main() {scanf( "%lld %d", &m, &k );memset( dp, -1, sizeof( dp ) );ll l = 1, r = 1e18;while( l <= r ) {ll mid = ( l + r ) >> 1, ans = calc( mid );if( ans == m ) return ! printf( "%lld", mid );else if( ans > m ) r = mid - 1;else l = mid + 1;}return 0;
}

T4:CF628D Magic Numbers

title

solution

这是道中规中矩的数位DPDPDP题目,只不过设计了一丁点的高精
按照套路我们会转化成[1,r]−[1,l−1][1,r]-[1,l-1][1,r][1,l1],但是l−1l-1l1涉及高精减,所以我们就单独拎出来
写一个checkcheckcheck专门判断lll是否符合,然后差分计算[1,r]−[1,l][1,r]-[1,l][1,r][1,l]

注意,题目翻译是错误的
是从高位到低位(从左往右)首位是奇数,然后偶数位,奇数位,偶数位

这种看代码就会秒懂的,不展开叙述
在这里插入图片描述

code

#include <cstdio>
#include <cstring>
#define mod 1000000007
#define ll long long
int m, d, len;
ll ans;
int num[2005];
char l[2005], r[2005];
ll dp[2005][2005];ll dfs( int pos, int sum, bool lim ) {if( pos == -1 ) return ( sum == 0 );if( ! lim && ~ dp[pos][sum] ) return dp[pos][sum];int up = lim ? num[pos] : 9;ll ans = 0;for( int i = 0;i <= up;i ++ ) {if( ( ( len - pos ) & 1 ) && i == d ) continue;if( ( ! ( ( len - pos ) & 1 ) ) && i != d ) continue;ans = ( ans + dfs( pos - 1, ( sum * 10 + i ) % m, lim && ( i == up ) ) ) % mod;}if( ! lim ) dp[pos][sum] = ans;return ans;
}ll calc( char *x ) {len = strlen( x );for( int i = 0;i < len;i ++ )num[len - i - 1] = x[i] - '0';return dfs( len - 1, 0, 1 );
}bool check() {len = strlen( l );ll sum = 0;for( int i = 0;i < len;i ++ ) {int j = l[i] - '0';if( ( ( i + 1 ) & 1 ) && j == d ) return 0;if( ( ! ( ( i + 1 ) & 1 ) ) && j != d ) return 0;sum = ( sum * 10 + j ) % m;}return ( sum == 0 );
}int main() {memset( dp, -1, sizeof( dp ) );scanf( "%d %d %s %s", &m, &d, l, r );ans = ( calc( r ) - calc( l ) + mod ) % mod;ans += check();printf( "%lld", ans % mod );return 0;
}

T5:CF855E Salazar Slytherin’s Locket

title

solution

这个也是很简单的数位DPDPDP,只不过中间我们套一个状压DPDPDP
如果状态sss的第iii位为000,表示数字iii出现了偶数次,反之出现奇数次
转化成bbb进制直接搞就行了呗
在这里插入图片描述

code

#include <cstdio>
#include <cstring>
#define ll long long
int Q, b;
int num[70];
ll l, r;
ll dp[12][70][( 1 << 11 ) - 1];ll dfs( int pos, int s, bool zero, bool lim ) {if( !pos ) return !s;if( ~dp[b][pos][s] && !zero && !lim ) return dp[b][pos][s];int up = lim ? num[pos] : b - 1;ll ans = 0;for( int i = 0;i <= up;i ++ )ans += dfs( pos - 1, ( !i && zero ) ? s : s ^ ( 1 << i ), zero && !i, lim && ( i == up ) );if( !zero && !lim ) dp[b][pos][s] = ans;return ans;
}ll solve( ll x ) {int len = 0;while( x ) num[++ len] = x % b, x /= b;return dfs( len, 0, 1, 1 );
}int main() {memset( dp, -1, sizeof( dp ) );scanf( "%d", &Q );while( Q -- ) {scanf( "%d %lld %lld", &b, &l, &r );printf( "%lld\n", solve( r ) - solve( l - 1 ) );}return 0;
}

T6:CF1245F Daniel and Spring Cleaning

title

solution

异或可以转化成二进制下不进位加法
朴素数位DPDPDP直接上
在这里插入图片描述

code

#include <cmath>
#include <cstdio>
#include <cstring>
#define ll long long
int T, L, R;
ll dp[40][2][2];ll dfs( int pos, bool limL, bool limR ) {if( pos == -1 ) return 1;if( ~ dp[pos][limL][limR] ) return dp[pos][limL][limR];dp[pos][limL][limR] = 0;int upL = limL ? ( L >> pos ) & 1 : 1;int upR = limR ? ( R >> pos ) & 1 : 1;for( int i = 0;i <= upL;i ++ )for( int j = 0;j <= upR;j ++ )if( ! ( i & j ) )dp[pos][limL][limR] += dfs( pos - 1, limL && ( i == upL ), limR && ( j == upR ) );return dp[pos][limL][limR];
}ll solve( int l, int r ) {if( l == -1 ) return 0;memset( dp, -1, sizeof( dp ) );L = l, R = r;dfs( log2( R + 1 ) + 1, 1, 1 );
}int main() {scanf( "%d", &T );while( T -- ) {int l, r;scanf( "%d %d", &l, &r );printf( "%lld\n", solve( r, r ) - solve( l - 1, r ) * 2 + solve( l - 1, l - 1 ) );}return 0;
}

T7:CF95D Horse Races

title

code

直接看代码即可

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define mod 1000000007
#define ll long long
int T, k;
int num[1005];
char l[1005], r[1005];
ll dp[1005][1005][2];
//pos表示当前位置
//d表示k+1减去与前一个幸运数字的距离
//那么当d降到0时,它与前面的幸运数字的距离就超过k了
//flag表示之前是否符合要求,符合要求为1,不符合为0
//lim表示当前位能否取到9,即之前是否达到上界,达到上界就为1,没有就为0
ll dfs( int pos, int d, bool flag, bool lim ) {if( ! pos ) return flag;if( ! lim && ~ dp[pos][d][flag] ) return dp[pos][d][flag];int up = lim ? num[pos] : 9;ll ans = 0;for( int i = 0;i <= up;i ++ ) {if( i != 4 && i != 7 )ans = ( ans + dfs( pos - 1, max( d - 1, 0 ), flag, lim && ( i == up ) ) ) % mod;elseans = ( ans + dfs( pos - 1, k, flag || d, lim && ( i == up ) ) ) % mod;}if( ! lim ) dp[pos][d][flag] = ans;return ans;
}ll calc( char *x ) {int len = strlen( x );for( int i = len - 1;i >= 0;i -- )num[len - i] = x[i] - '0';return dfs( len, 0, 0, 1 );
}bool check() {int len = strlen( l ), last = 0x3f3f3f3f;for( int i = len - 1;~ i;i -- ) {int j = l[i] - '0';if( j == 4 || j == 7 ) {if( last - i <= k ) return 1;else last = i;}}return 0;
}int main() {memset( dp, -1, sizeof( dp ) );scanf( "%d %d", &T, &k );while( T -- ) {scanf( "%s %s", l, r );printf( "%lld\n", ( calc( r ) - calc( l ) + check() + mod ) % mod );}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/317883.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#如何安全、高效地玩转任何种类的内存之Memory(三)

前言我们都知道&#xff0c;.Net Core是微软推出的一个通用开发平台&#xff0c;它是跨平台和开源的&#xff0c;由一个.NET运行时、一组可重用的框架库、一组SDK工具和语言编译器组成&#xff0c;旨在让.Net developers可以更容易地编写高性能的服务应用程序和基于云的可伸缩服…

.netcore下的微服务、容器、运维、自动化发布

微服务1.1 基本概念1.1.1 什么是微服务&#xff1f;微服务架构是SOA思想某一种具体实现。是一种将单应用程序作为一套小型服务开发的方法&#xff0c;每种应用程序都在其自己的进程中运行&#xff0c;并采用轻量级的通讯机制&#xff08;TCP&#xff09;进行通信。这…

[选拔赛1]花园(矩阵快速幂),JM的月亮神树(最短路),保护出题人(斜率优化)

多年不考试&#xff0c;一夜回到解放前T1&#xff1a;花园titlesolutioncodeT2&#xff1a;月亮神树titlesolutioncodeT3&#xff1a;保护出题人titlesolutioncodeT1&#xff1a;花园 title 小 L 有一座环形花园&#xff0c;沿花园的顺时针方向&#xff0c;他把各个花圃编号为…

.NET的关于人脸识别引擎分享(C#)

最近在Github上找合适的人脸识别引擎&#xff0c;想要本地化用&#xff0c;不用开放的一些API&#xff08;比如腾讯AI、百度AI&#xff09;,有些场景联不了网&#xff0c;一开始搜索的是时候&#xff08;关键字&#xff1a;face recognition&#xff09;就找到了最出名的face_r…

UOJ#84-[UR #7]水题走四方【dp】

正题 题目链接:https://uoj.ac/problem/84 题目大意 有nnn个点的一棵树&#xff0c;111为根&#xff0c;两个人从根节点往下走&#xff08;只能从深度小的点走到深度大的点&#xff09;。 两个人每一秒都可以一条边&#xff08;也可以不移动&#xff09;&#xff0c;或者不消…

Docker最全教程——数据库容器化(十一)

终于按时完成第二篇。本来准备着手讲一些实践&#xff0c;但是数据库部分没有讲到&#xff0c;部分实践会存在一些问题&#xff0c;于是就有了此篇以及后续——数据库容器化。本篇将从SQL Server容器化实践开始&#xff0c;并逐步讲解其他数据库的容器化实践&#xff0c;中间再…

[选拔赛2 NOIP2018雅礼集训 Day3 u,v,w]玩个三角形(二维差分),玩个球(状压DP+map),玩个树(树上DP)

文章目录T1&#xff1a;玩个三角形titlesolutioncodeT2&#xff1a;玩个球titlesolutioncodeT3&#xff1a;玩个树titlesolutioncodeT1&#xff1a;玩个三角形 title 题目描述 考虑一个 n ∗ n 的矩阵 A&#xff0c;初始所有元素均为 0。 执行 q 次如下形式的操作&#xff…

2019 年起如何开始学习 ABP 框架系列文章-开篇有益

阅读文本大概需要 3.3 分钟。本系列文章推荐阅读地址为&#xff1a;52ABP 开发文档https://www.52abp.com/Wiki/52abp/latest/Welcome-to-52abp本文的目的是为了让刚刚接触 ABP 框架的同学或者准备接触 ABP 框架的同学&#xff0c;能够理解和搞明白 ABP 框架到底是怎么回事&…

【模板】差分约束算法

【模板】差分约束算法 题意&#xff1a; 题解&#xff1a; 模板题 算法讲解 给出一组包含 m 个不等式&#xff0c;有 n 个未知数。求任意一组满足这个不等式组的解&#xff0c;或判定无解。 连边之后跑最短路&#xff0c;保证每个连通块都没有负环即可。 也可以建源点s 0&a…

数论一之定理证明——裴蜀/威尔逊/费马/扩展欧几里得/[扩展]欧拉/[扩展]中国剩余定理,欧拉函数,逆元,剩余系,筛法

打死没想到会在H老师处学懂数论同余&#xff0c;整除模运算埃式筛法欧拉筛法最大公约数和最小公倍数辗转相除法更相减损术裴蜀定理威尔逊定理费马定理同余等价类、剩余系、缩系欧拉函数欧拉定理扩展欧拉定理区间逆元扩展欧几里得中国剩余定理扩展中国剩余定理利用以上所有知识进…

AT4437-[AGC028C]Min Cost Cycle【结论,堆】

正题 题目链接:https://www.luogu.com.cn/problem/AT4437 题目大意 有nnn个点的一张有向完全图&#xff0c;每个点有两个点权a,ba,ba,b。连接x,yx,yx,y两个点的边权为min{ax,by}min\{a_x,b_y\}min{ax​,by​}&#xff0c;求一条权值和最小的哈密顿回路。 1≤n≤105,1≤a,b≤1…

某银行大型管理系统端到端持续集成和交付实践

背景传统的银行IT系统研发流程从需求提出到产品交付往往具有较长的研发周期&#xff0c;纵观银行当下面临的市场环境&#xff0c;个人信贷消费升级&#xff0c;资管需求旺盛&#xff0c;普惠金融成为国家战略&#xff0c;来自银行同业和互联网金融的压力扑面而来&#xff0c;谁…

排列组合十一个性质公式及证明,错排数公式及证明

文章目录排列数组合数求组合数常用公式定义式递推式杨辉三角组合数常用性质及证明性质一性质二性质三性质四(二项式定理)性质五性质六性质七性质八性质九性质十性质十一错排数排列数 从nnn个物品中不放回地依次选mmm个物品&#xff0c;考虑顺序&#xff0c;有多少种方案&#…

引入用于 Azure IoT Edge 的 Visual Studio 工具

物联网开发人员&#xff1a;工具和经验引入用于 Azure IoT Edge 的 Visual Studio 工具今天&#xff0c;我们很高兴地发布用于 Visual Studio 2017 的 Azure IoT Edge 工具的预览版。Azure IoT Edge 是一个全托管服务&#xff0c;通过直接在跨平台物联网设备上部署并运行人工智…

P4878 [USACO05DEC]Layout G

P4878 [USACO05DEC]Layout G 题意&#xff1a; 题解&#xff1a; 这个题其实是差分约束的裸题&#xff0c;但是有几个坑要注意 1.题目说了&#xff0c;奶牛按照编号1…N排列&#xff0c;对于ML个输入&#xff0c;A< B ,所以关系是B - A < 10,而不是A - B <10,我一开…

【学习笔记】原根 / BSGS / 扩展BSGS证明及模板

文章目录原根BSGS大步小步算法扩展BSGS原根 如果两个整数a,ba,ba,b互质&#xff0c;则有aϕ(b)%b1a^{\phi(b)}\%b1aϕ(b)%b1 定义模bbb意义下的aaa的阶为使ad%b1a^d\%b1ad%b1的最小正整数ddd 显然&#xff0c;模bbb的阶d∣ϕ(b)d|\phi(b)d∣ϕ(b) 如果模bbb意义下aaa的阶为…

.Net Core分布式部署中的DataProtection密钥安全性

在.NetCore中默认使用DataProtection来保护数据&#xff0c;例如Cooike等。一般情况下DataProtection生成的密钥会被加密后存储&#xff0c;例如默认的文件存储可以看到使用了Windows DPAPI加密。但是如果更改默认设置例如使用的外部存储如redis则此时密钥默认是不加密的微软说…

scanf(“%s“)真的只开读入字符串大小就可以了吗??

文章目录前言还原过程计算机程序背后的故事总结瞎逼逼前言 艹艹艹艹艹艹&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;老子没想到没想到&#xff0c;靠&#xff01; 本人刚刚在做树链剖分“染色”一题的代码重构&#xff0c;上午打…

P5299-[PKUWC2018]Slay the Spire【dp】

前言 正题 题目链接:https://www.luogu.com.cn/problem/P5299 题目大意 有2n2n2n张牌&#xff0c; nnn张强化牌&#xff0c;每张上有一个正整数x(x>1)x(x>1)x(x>1)&#xff0c;如果使用后之后的每一张攻击牌伤害都会乘上xxx。nnn张攻击牌&#xff0c;每张上有一个正…

asp.net core2.2 多用户验证和授权

asp.net core2.2 用户验证 和授权有很详细和特贴心的介绍&#xff0c;我感兴趣的主要是这两篇&#xff1a;cookie身份验证基于角色的授权我的项目有两类用户&#xff1a;微信公众号用户&#xff0c;用户名为公众号的openid企业微信的用户&#xff0c;用户名为企业微信的userid每…