首页 > 其他分享 >abc194f O(nk)题解

abc194f O(nk)题解

时间:2023-11-02 13:55:05浏览次数:37  
标签:nk 17 16 题解 LL times dp abc194f

前言

洛谷唯一的题解似乎是 \(O(nk^2)\) 的,怎么卡过去的orz

这里提供一种与 AT 官方题解时间复杂度相同的 \(O(nk)\) 做法。

Solution

题意很显然,就不解释了。

一眼丁真,考虑数位 dp。

设 \(dp_{i,j}\) 表示做到第 \(i\) 位,不同的个数有 \(j\) 种的方案数。

显然有转移方程:

\(dp_{i,j}=dp_{i-1,j}\times j +dp_{i-1,j-1} \times (16-j-1)\)

边界为 \(dp_{1,1}=15\)。

分类讨论,考虑存在前导 0 与不存在前导 0。

当前导 0 存在时,由于每种方案中最高位数字的方案数是相等的,因此显然总方案数为 \(\frac{15}{16}\sum_{i=1}^{n}dp_{i,k}\)。

而当不存在时,将数字分为已出现过和未出现过两种,分别计算个数。

两种唯一的区别为已钦定选择的数字个数。则在第 \(i\) 位时,若前面已有 \(x\) 个数已被选,方案数为 \(\binom{16-x}{k-x} \times \sum_{j=k-x}^{\min(n-i,k)} \frac{dp_{n-i,j}\times\binom{x}{j-k+x}}{\binom{16}{j}}\),具体可以用组合意义推导得到。

应该还可以再化简,但是这样就已经能做了。

实际实现的时候由于组合数的上下标不超过 16,因此可以提前预处理。

code

#include <bits/stdc++.h>
#define LL long long
using namespace std;
LL n,i,j,k,m,tmp1,tmp2,tmp3,ans=0;
LL mod=1000000007;
LL val[17],C[17][17],invC[17][17],dp[200005][17];
string s;
bool flag[17];
void exgcd(LL a,LL b,LL &x,LL &y,LL &val){
	if(b==0){
		val=a;
		x=1;
		y=0;
	}
	else{
		exgcd(b,a%b,y,x,val);
		y-=x*(a/b);
	}
}
LL doit(char ch){
	if(ch>='0' && ch<='9') return ch-'0';
	else return ch-'A'+10;
}
LL inv(LL x){
	tmp1=0,tmp2=0,tmp3=0;
	exgcd(x,mod,tmp1,tmp2,tmp3);
	return (tmp1+mod)%mod;
}
int main() {
    val[0]=1;
    for(i=1;i<=16;i++){
    	val[i]=val[i-1]*i%mod;
    	val[i]%=mod;
	}
	for(i=1;i<=16;i++)
	  for(j=0;j<=i;j++)
	    C[i][j]=val[i]*inv(val[i-j])%mod*inv(val[j])%mod;
	for(i=1;i<=16;i++)
	  for(j=0;j<=i;j++)
	    invC[i][j]=inv(C[i][j]);
	cin>>s>>k;
	n=s.length();
	dp[0][0]=1;
	dp[1][1]=16;
	C[0][0]=1;
	invC[0][0]=1;
	for(i=2;i<=n;i++)
	  for(j=1;j<=16;j++){
	  	dp[i][j]=(dp[i-1][j]*j%mod+dp[i-1][j-1]*(16-(j-1))%mod);
	  	dp[i][j]%=mod;
	  }
	for(i=1;i<n;i++){
		ans+=(dp[i][k]*inv(16)%mod*15ll%mod)%mod;
		ans%=mod;
	}
	ans+=((dp[n-1][k-1])*1ll*C[15][k-1]%mod*invC[16][k-1]%mod+(dp[n-1][k]*1ll*C[15][k-1]%mod*invC[16][k])%mod)%mod*(doit(s[0])-1)%mod;
	ans%=mod;
	LL sum1,sum2,now=1;
	flag[doit(s[0])]=true;
	for(i=1;i<s.length();i++){
		sum1=0,sum2=0;
	    for(j=0;j<doit(s[i]);j++){
	    	if(flag[j]==true){
	      	    sum1++;
		    }
		    else sum2++;
		}
		for(j=k-now;j<=k;j++){
			ans+=sum1*dp[n-i-1][j]%mod*C[16-now][k-now]%mod*C[now][j-(k-now)]%mod*invC[16][j]%mod;
			ans%=mod;
		}
		if(now+1<=k){
			for(j=k-now-1;j<=k;j++){
				ans+=sum2*dp[n-i-1][j]%mod*C[16-now-1][k-now-1]%mod*C[now+1][j-(k-now-1)]%mod*invC[16][j]%mod;
				ans%=mod;
			}
		}
		if(flag[doit(s[i])]==false) now++;
	    flag[doit(s[i])]=true;
	    if(now>k) break;
	}
	if(now==k) ans++;
	printf("%lld",ans%mod);
	  
	return 0;
}

标签:nk,17,16,题解,LL,times,dp,abc194f
From: https://www.cnblogs.com/monster-hunter/p/17805227.html

相关文章

  • 提交GitLab代码自动触发jenkins运行
    利用jenkins和gitlab的webhook结合,实现提交代码之后,自动触发jenkins的构建1、插件安装首先jenkins需要安装两个gitlab的插件分别为:(GenericWebhookTriggerPlugin)和(gitlab)。安装完成以后jenkins的GenericWebhookTrigger配置Token。2、在gitlab设置webhook设置前先配置一下GitLab......
  • [ARC159F] Good Division 题解
    [ARC159F]GoodDivision题解首先对于题目要求的划分方式转化一下,转化为划分的每一段都没有绝对众数,可以证明这与题目中的要求是完全等价的,证明如下:充分性:考虑构造一种操作方法,就是每次操作都消去一个出现次数最多的数,按照这样操作可以保证每次操作之后该区间仍然不会出现绝对......
  • Thinkpad 智能控温系统TPFanControl软件安装教程
    由于原来的tpfancontrol.com已经下线了,现在的TPFanControl可以到https://thinkwiki.de/TPFanControl里面进行下载,这里面复制了之前TPFanControl.com的页面,直接拉到下面点击下载: 下载安装后如果发现乱码,可以在页面FAQ下找到解决乱码的方案:问题描述是,在远东地区的windows......
  • 使用docker 部署testlink
    docker部署testlink1、拉取db镜像:dockerpullbitnami/mariadb 2、拉取testlink镜像:dockerpullbitnami/testlink3、容器网络:docker networkcreatetestlink4、查看网络:dockernetworkls 4.1、删除网络 dockernetworkrm<networkname>5、创建数据库卷......
  • 下载低版本jenkins
    一目的下载低版本jenkins地址:https://get.jenkins.io/war-stable/二步骤1.进入下载页,选择stable版,PastReleases 2.查看版本对应关系,选择合适版本  ......
  • linux安装Jenkins
    一目的安装Jenkins说明:安装步骤主要从官网获取:https://www.jenkins.io/ 二准备1.Jenkins需要jdk环境安装jdk: https://www.cnblogs.com/qxAndWorld/p/17804671.html2.下载Jenkins的war包https://www.cnblogs.com/qxAndWorld/p/17804775.html  三步骤 1.将wa......
  • 无法加载文件 E:\nodejs\node_global\npm.ps1,因为在此系统上禁止运行脚本。有关详
    npminstall报错解决办法打卡windospowershell并且以管理员运行输入命令set-executionpolicyremotesignedY......
  • 10.30 CF1685 题解
    10.30CF1685A.CircularLocalMiniMax题意给你\(n\)个整数$a_1,a_2,\ldots,a_n$。问有没有可能将它们排列在一个圆上,使每个数字严格地大于其相邻的两个数字或严格地小于其相邻的两个数字?题解直接排序然后按照\(1,4,2,5,3,6\)的规律放,check一下合不合法就行了。......
  • 题解:[SCOI2008] 城堡
    应该是联赛前最后一次任性了,浪费的时间有点多,不过也揭露了我的基础知识和代码能力都很弱的问题,得加油啊。先stodwt。给定一棵基环树森林,起初有\(m\)个点已被选进\(S\)里,你需要再选\(k\)个点加入到\(S\)中,最小化其余点到\(S\)距离的最大值。这个问题直接做非常困难,......
  • Luogu P3862 数圈 题解
    看数据范围——题记传送门考虑记\(f_i\)表示有\(i\)个点的完全图的圈数\(g_i\)表示有\(i\)个点的完全图中一个点到另一个点不同路径的方案数\(ans\)表示答案容易知道递推式\[f_i=g_{i-1}\timesC_{i-1}^2+f_{i-1}\]\[g_i=g_{i-1}\times(i-2)+1\]\[ans=f_{n-......