2022ICPC杭州(ACK)

A

exgcd

exgcd(a,b,x,y)a,b已知,用于求解ax+by=gcd(a,b)中的某一组解 x,y;而求ax+by=kgcd(a,b) 的解,只需要将 exgcd(a,b,x,y) 求出的x,y 同时乘上 k 即可。

具体题解:
pEnn724.jpg

code

C

被复杂题意包装起来的01背包。

简化一下题意就是:有n个物品,背包体积为k,第i个物品的体积为p[i],且有p[i]种价值,其中只有一种价值对应“全部升级”(价值为w[i][p[i]]),剩下p[i]1种价值对应“部分升级”(价值对应w[i][1p[i]1])。可以选择至多一个物品“部分升级”,其他必须为“全部升级”。设选取的“全部升级”的物品总体积为sum,则“部分升级”物品的价值为w[i][ksum]。求可获最大价值。

可以将物品的p[i]个价值看做:物品的体积为j时(j[1,p[i]]),价值为w[i][j](可以证明这种定义方式与题意等价)。这样,就规定选取的物品存在“部分升级”时,总价值必须恰好为k。因此在初始化dp数组时必须为INF(对于未规定选取恰好体积时初始化为0)。

特点在于p[i]<=10,且至多只能有一个“部分升级”的物品。所以状态可设置为:

dp[i][j][0/1]:考虑前i个物品,选取物品的总体积为j,且选了0/1个“部分升级”的物品,最大总价值。

可以直接暴力枚举“部分升级”物品的所有价值并转移,转移时对于第i种物品,考虑3种情况即可:

  1. 不选第i个物品(不代表真的不选,而是作为题中sum>k的那部分,价值为 0 地选择该物品,相当于不选。这里容易混淆)-> 从前缀的状态转移
  2. i个物品“全部升级” -> “部分升级”的0/1状态均能转移
  3. i个物品“部分升级” -> 由于最多只能选一个,则只能从已选“部分升级”的 0 状态转移

注意当k特别大时,所有物品不能装满背包,这时所有物品必须均为“全部升级”状态。而dp只处理了选取恰好体积的情况,故需要特判k很大的情况。(如果不特判,而是采用枚举dp[n][0m][0/1]的方式更新答案,则会有一种情况导致错误:某个物品“部分升级”比“全部升级”的价值更大,导致对这个物品进行选择时,在背包体积足够时,选了该物品“部分升级”的情况。虽然这样的情况答案更优,但却是不合法的,因为在背包体积足够的情况下,所有物品必须“全部升级”。具体见WA on 7)

可以倒序枚举体积,省去01背包dp数组中物品个数的那一维。

具体实现见代码

复杂度O(nk10)

ACcode

WA on 7

K

字典树

考虑逆序对的贡献是怎样产生的。

分析后可发现,逆序对产生的方式有两种:

  1. 两个字符串的前i1个字符相同,第i个字符不同
  2. 一个字符串是另一个字符串的前缀

f[x][y]表示在给定的字符串序列中,(str1,str2)对的数量,其中(str1,str2)满足:

  1. str1str2 之前
  2. 存在一个位置 i ,使得str1[1i1]==str2[1i1]
  3. str1[i]==x,str2[i]==yx,y表示字符。

ans1=

seq[x]>seq[y]f[x][y]

其中seq[x]为字符x在当前给定的字母表中的位置。

计算ans2:在插入某个字符串str前,用这个字符串跑一遍字典树,若可到str的末尾,则看其末尾之后的前缀数量,这些字符串都可以使得str是它们的真前缀,自然和str构成逆序对。对于每个字符串,在插入前做这样的统计即可。注意走不到末尾时不能作统计,具体实现见代码。

code

posted @   jxs123  阅读(2)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示
主题色彩