8.12模拟:dp递推

文章目录

  • 前言
  • 本次最大收获
  • 考场
  • 复盘
    • T1 lecture
    • T2 n-thlon
    • T3 assignment
    • T4 recoverset
  • 总结

前言

245分
100+70+40+35
不太满意qwq
被KH暴打
后三道题全是部分分
而且T2和T3关键性质都出来了,距离正解只差临门一脚
但是就差了这一脚
感觉今天T2、T3全是折在了刷表法上呢…
T4后面的65考场上确实不太可做
但至少现在挂分少了很多吧

本次最大收获

刷表法的记忆化搜索复杂度是假的
血的教训!

考场

开局先遍历
T1数位裸题
T2第一看觉得有点恶心(主要是期望dp做的太少了)
T3乍一看:字好多(第一次遍历不咋动脑子,基本字多的我都看不出来啥…)
T4题面和数据点分布似乎都在说本题您会爆零

和昨天一样,先把签到题T1切了,稳一下心态
有一说一这个数位比YBT的好多阴间数位友善多了
后导零的处理和正常略有不同,调了一会
8:45左右过了样例3,基本没问题了

因为T2T3主观上没有太大倾向,所以就决定先看T2
仔细想想T2的转移还是很好出来的
但是朴素转移明显比正解差了一维
抱着脑袋神游了矩阵快速幂等神仙操作
然并卵
70也算不错了
就去了T3

T3就是看着字挺多其实抽象出来很简单的题
给一个集合,要把它分成s份,每份代价是西格玛*(size-1)
求最小代价
很容易想到他肯定是要sort一下然后约取越短
但直接转移显然是n3的,因为没有利用到越取越短的性质,只有65
所以我就想到了记忆化搜索,利用不能比上一次取得长剪枝
但填表记忆化搜索不太好转移这个诡异的状态
于是开始刷表法的记忆化搜索
(伏笔)

去到T4,大概9:50左右
看s的大小那么小,似乎还是有搞头的
想到可以从小到大从背包取答案并不断从方案背包里删除这个元素
很愉快的拿到了35并且把我继续做65的路子给堵死了
其实负值时想过从最大值走
但是想到可能是减正的或者加负的两种情况无法判断就放弃了
忽略了其中绝对值的统一性

全做完大概10:50左右
时间剩的比较少了
毕竟这次写的分明显不太够
我想扣一道正解出来
但连检查带想的从头到尾遍历了一遍,还是没什么思路
时间就过去了大半
时间到了最后半个多小时我甚至都不太敢想正解了
因为感觉想出来也没时间写了qwq
就这样在矛盾中把时间浪费完了

复盘

事实是T2T3要是正解出来了加起来改过也不用20min
就是差一点qwq

T1 lecture

确实是比较裸的数位
连求[l,r]的答案这种东西都没有
有些不同的地方是因为要整除k的后缀所以从低位到高位填
(这紫题就离谱)

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+100;
int n,mod,k;
int dp[1050][105][2];//dp[pos][mod][op]
int mi[1050];
void print(int k){for(int i=1;i<k;i++) printf("  ");
}
int find(int pos,int res,int op,int zero){
//	print(pos);printf("pos=%d res=%d op=%d zero=%d\n",pos,res,op,zero);if(pos>n){return op ? 1 : 0;}if(!zero&&dp[pos][res][op]!=-1) return dp[pos][res][op];int ans=0;for(int i=0;i<=9;i++){if(pos==n&&i==0) continue;int nres=(res+i*mi[pos-1])%k;int nz=zero&&i==0;if(op){ans+=find(pos+1,nres,1,nz);ans%=mod;}else{int nop= nres==0&&nz==0 ?1:0;
//			print(pos+1);printf("i=%d nres=%d nop=%d ans=%d\n",i,nres,nop,ans);ans+=find(pos+1,nres,nop,nz);ans%=mod;}}if(!zero) dp[pos][res][op]=ans;
//	print(pos);printf("return: pos=%d res=%d op=%d zero=%d ans=%d\n",pos,res,op,zero,ans);return ans;
}
int main(){
//	freopen("lecture.in","r",stdin);
//	freopen("lecture.out","w",stdout);memset(dp,-1,sizeof(dp));scanf("%d%d%d",&n,&k,&mod);mi[0]=1;for(int i=1;i<=n;i++){mi[i]=(mi[i-1]*10)%k;}printf("%d\n",find(1,0,0,1));return 0;
}
/**/

T2 n-thlon

就是这么转移的啊!!!
我的注意力全在优化dp设计和转移方法上了
我那个代码瓶颈的for循环那么裸的从头加到尾
我愣是没看出来前缀和
枯了
也和我用刷表法相对不太好看出来有点关系
不好看出来个头啊

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+100;
int n,m;
double dp[105][N],sum[105][N],per;
int r[105],tot;
int mx,nmx;
double ask(int k,int p){return p<0?0:sum[k][p];
}
int main(){//freopen("nthlon.in","r",stdin);//freopen("nthlon.out","w",stdout);//printf("%d\n",sizeof(dp)/1024/1024);scanf("%d%d",&n,&m);if(m==1){printf("%.16lf\n",1.0);return 0;}per=1.0/(m-1);for(int i=1;i<=n;i++){scanf("%d",&r[i]);tot+=r[i];}dp[0][0]=1;for(int i=0;i<=tot;i++) sum[0][i]=1;for(int k=1;k<=n;k++){//nmx=0;for(int i=0;i<=tot;i++){dp[k][i]=(ask(k-1,i-1)-ask(k-1,i-m-1)-(ask(k-1,i-r[k])-ask(k-1,i-r[k]-1)))*per;}for(int i=1;i<=tot;i++){sum[k][i]=sum[k][i-1]+dp[k][i];}//	mx=max(mx,nmx);//for(int i=1;i<=tot;i++) printf("k=%d i=%d dp=%lf\n",k,i,dp[k][i]);}double ans=0.0;for(int i=1;i<tot;i++){ans+=dp[n][i];}ans*=(m-1);printf("%.16lf",ans+1.0);return 0;
}
/*
4
10
2
1
2
15 5
1 2 3 4 53 6
2 4 2
*/

T3 assignment

这个也就差一点

sert和越取越短的性质我都想到了
但是我没用好这个性质
直接反向优化了
我那个刷表的记忆化搜索复杂度假了
因为它相当于每更新一次答案都会往后一直到尾尝试一次更新
这复杂度直接裂开
再剪枝也没有用
还不如不优化,只剩下40(换句话说就是稍微大点的数据全T了)
其实我们因为越取越短的性质,[0,i] 分k短的最优解最后一段长度肯定不超过i/k下取整
所以复杂度大概是:

nn/1+nn/2+nn/3…nn/k

欧拉老爷子告诉我们,这个东西大概是

n*nlogn

然后就可解了

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=5e3+100;
const int M=5e4+100;
typedef pair<int,int>pr;
#define mp make_pair
int n,b,s,m;
struct node{int to,nxt,v;
}p1[M],p2[M];
int fi1[N],fi2[N],cnt1,cnt2;
void addline1(int x,int y,int v){p1[++cnt1]=(node){y,fi1[x],v};fi1[x]=cnt1;
}
void addline2(int x,int y,int v){p2[++cnt2]=(node){y,fi2[x],v};fi2[x]=cnt2;
}
int dis1[N],dis2[N];
int jd1[N],jd2[N];
priority_queue<pr,vector<pr>,greater<pr> >q;
void dij1(){memset(dis1,0x3f,sizeof(dis1));dis1[b+1]=0;	while(!q.empty()) q.pop();q.push(mp(0,b+1));while(!q.empty()){int now=q.top().second;q.pop();if(jd1[now]) continue;jd1[now]=1;for(int i=fi1[now];~i;i=p1[i].nxt){int to=p1[i].to;if(dis1[to]>dis1[now]+p1[i].v){dis1[to]=dis1[now]+p1[i].v;q.push(mp(dis1[to],to));}}}return;
}
void dij2(){memset(dis2,0x3f,sizeof(dis2));dis2[b+1]=0;	while(!q.empty()) q.pop();q.push(mp(0,b+1));while(!q.empty()){int now=q.top().second;q.pop();if(jd2[now]) continue;jd2[now]=1;for(int i=fi2[now];~i;i=p2[i].nxt){int to=p2[i].to;if(dis2[to]>dis2[now]+p2[i].v){dis2[to]=dis2[now]+p2[i].v;q.push(mp(dis2[to],to));}}}return;
}
ll v[N],sum[N];
ll dp[N][N],ans=2e15;//dp[pos][lft]
void dfs(int pos,int lft,int lst,ll val){if(dp[pos][lft]!=-1&&dp[pos][lft]<=val) return;else dp[pos][lft]=val;if(b-pos>lft*lst) return;if(pos>=n) return;if(lft==1){ans=min(ans,val+(sum[b]-sum[pos])*(b-pos-1));return;}for(int i=lst;i>=1;i--){dfs(pos+i,lft-1,i,val+(sum[pos+i]-sum[pos])*(i-1));} return;
}
int main(){
//	freopen("assignment.in","r",stdin);
//	freopen("assignment.out","w",stdout);memset(fi1,-1,sizeof(fi1));memset(fi2,-1,sizeof(fi2));scanf("%d%d%d%d",&n,&b,&s,&m);int x,y,z;for(int i=1;i<=m;i++){scanf("%d%d%d",&x,&y,&z);addline1(x,y,z);addline2(y,x,z);}dij1();dij2();for(int i=1;i<=b;i++) v[i]=dis1[i]+dis2[i];//printf("i=%d v=%lld\n",i,v[i]);sort(v+1,v+1+b);for(int i=1;i<=b;i++) sum[i]=sum[i-1]+v[i];for(int i=1;i<=n;i++) dp[i][1]=sum[i]*(i-1);for(int k=2;k<=s;k++){for(int i=k;i<=b;i++){dp[i][k]=2e15;for(int l=1;l<=i/k;l++){dp[i][k]=min(dp[i][k],dp[i-l][k-1]+(sum[i]-sum[i-l])*(l-1));}}}printf("%lld\n",dp[b][s]);return 0;
}
/*
5 4 2 10
5 2 1
2 5 1
3 5 5
4 5 0
1 5 1 
2 3 1
3 2 5
2 4 5
2 1 1
3 4 25 4 2 10
5 2 1
2 5 1
3 5 5
4 5 10
1 5 1
2 3 1
3 2 5 
2 4 5 
2 1 1
3 4 25 4 3 9
5 2 1
2 5 10
5 1 3
1 5 0
2 1 1
5 3 5
3 5 5
5 4 1000
4 2 0
*/

T4 recoverset

大黑题确实不太可做
从我考场上卡住的地方继续的话也不远了
我们发现最大值减次大值就是当前绝对值最小的元素的绝对值
然后我们如果就把它当正的处理,整个dp序列会向左平移vi的绝对值
因为是平移,相对关系不变,我们可以继续用最大减次大求下一个的绝对值
如法炮制后所有答案的绝对值就出来了
接下来添符号
首先,任务1全是非负时
所以元素全减完背包里应该剩个空集0
显然带负数是应该也是一样的
但是由于我们每次都当正的算整体向左移
所以这个空集早就负的没影了
我们加符号的任务就是把这个零点移动回到0的位置
把一个vi转负会使零点右移v[i]的单位
所以我们的合法方案其实就是用答案绝对值,凑出当前这个零点的绝对值
也就是个硬币背包
至于字典序最小的问题我们可以贪心的先尝试让绝对值最大的数加负号即可

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1e6+100;
int n,mod,k;
struct node{ll x,num;bool operator < (const node y)const{return x<y.x;}
}p[N];
map<ll,int>mp;
ll dp[N];
ll ans[N],tot,num;
bool jd[70][100020];
int main(){int t,cnt=0;//printf("%d",sizeof(jd)/1024/1024);scanf("%d",&t);while(t--){cnt++;tot=0;mp.clear();scanf("%d",&n);for(int i=1;i<=n;i++) scanf("%lld",&p[i].x);for(int i=1;i<=n;i++) scanf("%lld",&p[i].num);sort(p+1,p+1+n);for(int i=1;i<=n;i++){mp[p[i].x]=i;dp[i]=p[i].num;}int pl=n,nxt;while(pl){nxt=dp[pl]>1?pl:pl-1;while(nxt&&!dp[nxt]) nxt--;if(nxt==0) break;ans[++tot]=p[pl].x-p[nxt].x;ll now=ans[tot];//printf("pl=%d nxt=%d tot=%d now=%d\n",pl,nxt,tot,now);for(int i=1;i<=n;i++){if(now==0){dp[i]/=2;continue;}ll pre=p[i].x-now;int id=mp[pre];if(!id) continue;dp[i]-=dp[id];//	printf("i=%d id=%d dp=%d\n",i,id,dp[i]);}pl=nxt;while(pl&&!dp[pl]) pl--;}if(p[pl].x!=0){//	printf("x=%lld\n",p[pl].x);num=n;memset(jd,0,sizeof(jd));jd[0][mp[0]]=1;for(int i=0;i<tot;i++){for(int j=1;j<=num;j++){if(jd[i][j]==0) continue;jd[i+1][j]=1;int id=mp[p[j].x+ans[i+1]];if(!id){mp[p[j].x+ans[i+1]]=++num;id=num;p[num].x=p[j].x+ans[i+1];}jd[i+1][id]=1;}}
//			for(int i=1;i<=tot;i++){
//				for(int j=1;j<=num;j++) printf("i=%d j=%d x=%lld jd=%d\n",i,j,p[j].x,jd[i][j]);
//			}ll now=-p[pl].x;for(int i=tot;i>=1;i--){//	printf("i=%d now=%lld\n",i,now);for(int j=1;j<=num;j++){//		printf("  j=%d x=%lld jd=%d\n",j,p[j].x,jd[i-1][j]);}if(jd[i-1][mp[now-ans[i]]]){now-=ans[i];ans[i]=-ans[i];}}sort(ans+1,ans+1+tot);}printf("Case #%d: ",cnt);for(int i=1;i<=tot;i++) printf("%lld ",ans[i]);printf("\n");}return 0;
}
/*
3
8
0 1 2 3 4 5 6 7
1 1 1 1 1 1 1 1
4
0 1 3 4
4 4 4 4
5
-2 -1 0 1 2
1 2 2 2 11
6
-4 -2 -3 -1 0 1
2 4 2 4 2 2
*/

总结

好的地方是我现在看题的思路似乎逐渐靠谱了
T234其实都有了正解的模样
只是中间推到某步卡住了
(行百里者半九十)
还是有点可惜
所以以后我想题可能得适当的加深我思考的迭代搜索深度
遇见瓶颈别着急回溯,哪一下子突破了说不定就开朗了
但也不能一概而论,迭代深度太深可能会使思路中错误的搜索树过大
还是得积累比赛经验慢慢来吧

明天:杂题
真正的盲考了
这就很容易跑题了
千万不能贪
加油!awa

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

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

相关文章

NumSharp v0.6.1 科学计算库发布,支持标量和隐式转换

NumSharp&#xff08;Numerical .NET&#xff09;可以说是C&#xff03;中的科学计算库。 它是用C&#xff03;编写的&#xff0c;符合.netstandard 2.0库标准。 它的目标是让.NET开发人员使用NumPy的语法编写机器学习代码&#xff0c;从而最大限度地借鉴现有大量在python代码的…

【做题记录】CF1451E2 Bitwise Queries (Hard Version)

CF1451E2 Bitwise Queries (Hard Version) 题意&#xff1a; 有 \(n\) 个数( \(n\le 2^{16}\) &#xff0c;且为 \(2\) 的整数次幂&#xff0c;且每一个数都属于区间 \([0,n-1]\) ) 可以通过询问交互库不超过 \(n1\) 次询问&#xff0c;每次询问编号为 \(i,j\) ( \(1\le i,j \l…

P4301 [CQOI2013] 新Nim游戏

P4301 [CQOI2013] 新Nim游戏 题目&#xff1a; 在传统的Nim游戏基础上加一步&#xff0c;在第一个回合中&#xff0c;第一个游戏者可以直接拿走若干个整堆的火柴。可以一堆都不拿&#xff0c;但不可以全部拿走。第二回合也一样&#xff0c;第二个游戏者也有这样一次机会。从第…

51nod1667-概率好题【容斥,组合数学】

正题 题目链接:http://www.51nod.com/Challenge/Problem.html#problemId1667 题目大意 两个人。 第一个人有k1k_1k1​个集合&#xff0c;第iii个包括了范围[L1i,R1i][L1_i,R1_i][L1i​,R1i​]的整数。 第二个人有k2k_2k2​个集合&#xff0c;第iii个包括了范围[L2i,R2i][L2_i…

[Luogu2279][HNOI2003] 消防局的设立

文章目录题目法一&#xff1a;树上DP思路代码实现法二&#xff1a;贪心 搜索思路代码实现题目 2020年&#xff0c;人类在火星上建立了一个庞大的基地群&#xff0c;总共有n个基地。起初为了节约材料&#xff0c;人类只修建了n-1条道路来连接这些基地&#xff0c;并且每两个基…

8.13模拟:分治二分倍增快速幂

文章目录前言考场复盘T1 roadT2 shopT3 runT4 stairs总结前言 240分 100802040 T3少取了一个模结果全挂掉了&#xff08;好不容易推出来了…&#xff09; T2也因为各种奇怪的错误挂了分 qwq 吸取教训吧 考场 今天先看题 T1第一眼看错了题意觉得水的不行 T3YBT原题且很水 T2T…

dnSpy 强大的.Net反编译软件

一说起.net的反编译软件&#xff0c;大家首先想到的就是Reflector&#xff0c;ILSpy&#xff0c;dotPeek等等。而dnSpy同样是一款优秀的反编译软件&#xff0c;同时它是开源免费的。官方的描述是: dnSpy是一个调试器和.NET组件编辑器。 即使您没有任何可用的源代码&#xff0c;…

图的匹配

定义见&#xff1a;OI-Wiki 图的匹配 。 二分图 解法 \(1\) &#xff1a;网络流(通用) 二分图最大匹配可以转换成最大流(费用流)模型 。 如果使用 \(\operatorname{Dinic}\) 算法求该网络的最大流&#xff0c;复杂度\(O(\sqrt{n}m)\) 。 具体代码见博客文章网络流 。 解法 \(2\…

AT2161-[ARC065D]シャッフル/Shuffling【dp】

正题 题目链接:https://www.luogu.com.cn/problem/AT2161 题目大意 长度为nnn的0/10/10/1串&#xff0c;mmm个区间&#xff0c;你可以按照顺序任意排列区间中的数字&#xff0c;求最后的可能情况数。 保证给出区间的左端点不降。 1≤n,m≤30001\leq n,m\leq 30001≤n,m≤3000…

【acwing210 异或运算】

【acwing210 异或运算】 题意&#xff1a; 给定你由N个整数构成的整数序列&#xff0c;你可以从中选取一些&#xff08;甚至一个&#xff09;进行异或&#xff08;XOR&#xff09;运算&#xff0c;问所有能得到的不同的结果中第k小的结果是多少。 题解&#xff1a; 把所有数…

小奇探险

文章目录题目题解代码实现题目 小奇去遗迹探险&#xff0c;遗迹里有N个宝箱&#xff0c;有的装满了珠宝&#xff0c;有的装着废品。 小奇有地图&#xff0c;所以它知道每一个宝箱的价值&#xff0c;但是它不喜欢走回头路&#xff0c;所以要按顺序拿这N个宝箱中的若干个。 拿宝…

8.14 模拟:字符串

文章目录前言收获考场复盘T1 wordlistT2 passwordT3 readtreeT4 bracket总结前言 290分 2010070100 又被KH爆碾了qwq T1签到题脑抽写挂了80分… &#xff08;就差这80啊…&#xff09;、 收获 学会了启发式合并 还有一个把字符串所有后缀放进trie树的比较字符串的技巧 考场…

基于Asp.Net Core打造轻量级内部服务治理RPC(二 远程服务设计)

紧接上一篇《基于Asp.Net Core打造轻量级内部服务治理RPC(一)》文章。本文主要讲解基于Asp.Net Core的远程服务设计和实现。在上一篇中讲过,服务提供者提供的服务实际上就是一个Controller&#xff0c;那么是否在该程序中&#xff0c;服务都按照Asp.Net Core 中的Web Api的方式…

[TJOI2008]彩灯

题目&#xff1a; Peter 女朋友的生日快到了&#xff0c;他亲自设计了一组彩灯&#xff0c;想给女朋友一个惊喜。已知一组彩灯是由一排 N个独立的灯泡构成的&#xff0c;并且有 MM 个开关控制它们。从数学的角度看&#xff0c;这一排彩灯的任何一个彩灯只有亮与不亮两个状态&a…

51nod1229-序列求和V2【数学,拉格朗日插值】

正题 题目链接:http://www.51nod.com/Challenge/Problem.html#problemId1229 题目大意 给出n,k,rn,k,rn,k,r求 ∑i1nikri\sum_{i1}^ni^kr^ii1∑n​ikri 1≤T≤20,1≤n,r≤1018,1≤k≤20001\leq T\leq 20,1\leq n,r\leq 10^{18},1\leq k\leq 20001≤T≤20,1≤n,r≤1018,1≤k≤…

【做题记录】图论杂题

P1268 树的重量 $\texttt{solution}$ 算法&#xff1a;(贪心)\(\) 找规律 当 \(n2\) 时&#xff0c;显然答案就是 \(dis(1,2)\) 。 当 \(n3\) 时&#xff0c;答案&#xff1a; \[\dfrac{dis(1,3)dis(2,3)-dis(1,2)}{2} \]当 \(n\) 是任意的&#xff0c;第 \(n\) 条路径可以处于…

[NOIP 2009 提高组]最优贸易

勤劳的一更题目题解代码实现题目 C国有 n个大城市和 m 条道路&#xff0c;每条道路连接这n个城市中的某两个城市。任意两个城市之间最多只有一条道路直接相连。这 m 条道路中有一部分为单向通行的道路&#xff0c;一部分为双向通行的道路&#xff0c;双向通行的道路在统计条数…

8.15模拟:图论

文章目录前言收获考场复盘T1 recoverT2 teamT3 planT4 seqpath总结至暗时刻 前言 60分 303000 … 已经不是被KH爆碾的问题 &#xff08;KH屹立不倒%%%&#xff09; 昨天祈祷不要挂80了 结果今天挂了160&#xff08;还不算那个背包的70&#xff09; qwq 加油吧 奇怪的教训又增加…

Azure Service Fabric Mesh:一个构建任务关键型微服务的平台

本文要点Azure Service Fabric Mesh&#xff08;目前处于预览阶段&#xff09;是一个完全托管的服务&#xff0c;它使你可以使用“无服务器”方法构建、部署和管理由运行在容器中的多语言服务组成的应用程序。Azure Service Fabric Mesh 通过使用 Envoy Proxy 构建的软件定义网…

【做题记录】人类智慧

CF741C Arpa’s overnight party and Mehrdad’s silent entering 描述&#xff1a;有 \(2n\) 个人坐在一张圆桌&#xff0c;第 \(1\) 个位置与第 \(n\) 个位置相邻。现在给他们分配 \(1\) 或 \(2\) 两种食物。要求任意相邻的三个人食物不完全相同。求是否有可行的分配方案。 转…