二模 (7) day1

第一题:

题目大意:

给出数轴上N棵树的坐标和高度,如果两棵树之间的距离小于其中一颗树的高度,那么就有树会被挡住。因此要把一些树砍矮一点。求砍树的总高度最小值。

N<=100000;

 

解题过程:

1.水题,直接按坐标升序排个序,然后看某棵树左右的树会不会被挡住,砍掉相应的高度即可。。 特殊考虑最左边的树和最右边的树。

初始得分100.

 


 

第二题:

求从给定的n个数中取一些数(必须取),使得他们的乘积 mod p = c 的方案数。n≤32,p≤10^9,c≤10^9,a[i]<p,p 是质数

 

解题过程:

1.看到n<=32第一直觉就是 刘汝佳训练指南上提到的 “中途相遇法”, 前dfs 出 前n/2个数的乘积的方案数,用hash 挂链来存。。然后dfs后n/2个数,如果乘积mod p为a, 那么 只要 在前n/2个数中  找到  乘积mod p=x ,a*x mod p = c 的 x的方案数即可。  求解x就是解一个同余方程,可以用拓展欧几里得来实现。。结果考试的时候脑子短路了,怎么都写不出来。。。 (要抽点时间好好整一整它了) 初始得分10分。。

2.其实还有更加简单的方法求x,也是考试之后才想到的。。   根据 p是质数 ,那么 ap-1  ≡ 1 (mod p) 。 同余式两边同时乘c,ap-1 * c  ≡ c (mod p) 

那么x 就是 ap-2  * c   。 可以证明在p的范围内 x 有唯一解。。 如果 a=0 c!=0当然就无解喽,如果 a=0,c=0 ,那么 前n/2个数不管怎么取都可以,所以方案数就是2n/2  。。其实这是我写题解才发现的 "边界"。。不过不会出现这种情况,题目里有说a[i]<p,所以a[i]不管怎么乘都不会mod p=0,除非a[i]=0。。如果a[i]=0,那么只能说出题人心够狠。。

 


 

第三题:

题目描述:有一个英雄,初始生命值是 hp(生命值无上限),在接下来的 n 秒内,每秒会受到一次伤害,第i 秒受到的伤害值为 a[i]。这个英雄 4 有一个道具“魔杖”,魔杖的初始能量为 0,每受到一次伤害,积攒 1 点能量。在英雄受到伤害后,可以立即释放魔棒中的能量,恢复 15×[能量点数]的生命值,且魔棒的点数清零。释放能量有施法间隔 cd(cd 是正整数),即相邻的两次释放的时间间隔至少有 cd 秒。
任何时刻当 hp≤0 时视为死亡,问这个英雄存活下来的前提下, cd 的值最大可以是多少?

如果 cd 没有上限,输出“No upper bound.”;如果无论如何都不能存活,输出-1。  n≤500,|a[i]|≤1000。

 

解题过程:

1.第二题扩展欧几里得写不来。就跑来搞这题,结果只会用贪心处理 2种无解的情况:

首先要充分理解cd的含义。。如果cd=1,假设第1s末用了魔棒,第2s末就可以再次使用。

对于No upper bound的情况(cd无穷大,那么只有一次用魔棒的机会):只要让英雄不断挨打,如果不加血就要死,那么就让他加血,如果最后还没死,就是No upper bound。如果加血还是要死,那就真的死了。

对于无论如何都不能存活,输出-1的情况:假设cd=1,那么只要每次挨打过后都用魔棒加一次血。如果还是死,那就必死了。

 

2.对于有解的情况,看看数据范围就知道肯定不是贪心啦。。 至少我只能想到cd一好就用魔棒的贪心策略,但是有谁打dota魔棒cd一好就吃的。。。当然是要留着拿来耍操作 玩极限的喽 ><。 于是就打算二分CD,然后判断能否活下来。

一开始想到用三维的状态来表示,前i分钟,剩余j点能量,还要k分钟才能再次使用魔棒。。。  但是复杂度太高。。  考虑到除了第一次吃魔棒,其他时候吃都必须满足剩余能量大于等于CD

那么就用F[i][j][0] 表示 到第i分钟末(注意是末)为止,剩余能量为j,且第一次免费用的魔棒还没用,最多还能剩多少血。

对应的F[i][j][1]表示第一次免费魔棒已经用过了。

转移也比较奇葩。

当j>=2的时候 , F[i][j][0]=F[i-1][j-1][0]-cost[i] ;    F[i][j][1]=F[i-1][j-1][1]-cost[i];

当j=0的时候,那么第i分钟末肯定吃了一次魔棒;( 因此不存在状态F[i][0][0])

所以 F[i][0][1]=MAX { max{F[i-1][k][0]+15*k } , max{F[i-1][k][1] + 15*k} - cost[i] + 15;  +15是因为第i分钟也加了1点能量且在这分钟末被用掉了。 对于第一个max,k无要求,对于第2个条件,k必须大于等于CD,因为前面已经把免费用的魔棒用过了。

那么 就可以用一个g[i-1][0]  g[i-1][1]  分别来表示2个max的值了。

同理 F[i][1][1]=MAX { max{F[i-1][k][0]+15*k } , max{F[i-1][k][1] + 15*k} - cost[i]  第i分钟的能量没有用掉,所以不用+15;

或者F[i][1][1]可以直接等于F[i-1][0][1]-cost[i] (也是写题解的时候想到的。应该是对的,明天实验下);

另外f[i][1][0]=f[i-1][0][0]-cost[i]。  

所以感觉 不用分j>=2来讨论,直接j>=1的全部归为一种即可。

 

表达能力有限,贴个代码(只贴判断能否活下来的函数吧),写得很挫。(貌似标准算法是差分约束系统?不过本弱渣不会额。。)

 

 1 bool check(int mid)
 2 {
 3     memset(f,0,sizeof(f));
 4     memset(g,0,sizeof(g));
 5     
 6     f[0][0][0]=hp;
 7     g[0][0]=hp;
 8     
 9     for (int i=1;i<=n;i++)
10     {
11         for (int j=2;j<=i;j++)
12         {
13             f[i][j][0]=f[i-1][j-1][0]-a[i];
14             f[i][j][1]=f[i-1][j-1][1]-a[i];
15             if (f[i][j][0]>0)
16                 g[i][0]=max(g[i][0],f[i][j][0]+j*15);
17             if (f[i][j][1]>0 && j>=mid)
18                 g[i][1]=max(g[i][1],f[i][j][1]+j*15);
19         }
20         f[i][1][0]=f[i-1][0][0]-a[i];
21         if (f[i][1][0]>0)
22             g[i][0]=max(g[i][0],f[i][1][0]+15);
23             
24         if (max(g[i-1][0],g[i-1][1])>a[i] && max(g[i-1][0],g[i-1][1])>0)
25             f[i][0][1]=max(g[i-1][0],g[i-1][1])+15-a[i];
26         if (max(g[i-1][0],g[i-1][1])>0)
27             f[i][1][1]=max(g[i-1][0],g[i-1][1])-a[i];
28     }
29     for (int i=0;i<=n;i++)
30         if (f[n][i][0]>0 || f[n][i][1]>0)
31             return true;
32     return false;
33 }
View Code

 

一开始把CD理解错了,结果答案全部相差1了。。只对了无解的2个点。。20分。 感觉自己还是太弱了。。最后把ans-1去掉就操过去了说。。

 

转载于:https://www.cnblogs.com/vb4896/p/4003674.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
请逐条解释分析下面这段程序:ops=sdpsettings('solver','cplex'); solvesdp(C,-f,ops); Pc=[double(Pc1),double(Pc2),double(Pc3)]; Pb=double(Pb); Ps_day=double(Ps_day); Pb_day=double(Pb_day); S=double(S); Pch=double(Pch); Pdis=double(Pdis); Cost_total=double(f) Price_Charge=double(Ce); Ce=sdpvar(24,1);%电价 z=binvar(24,1);%购售电状态 u=binvar(24,1);%储能状态 Pb=sdpvar(24,1);%日前购电 Pb_day=sdpvar(24,1);%实时购电 Ps_day=sdpvar(24,1);%实时售电 Pdis=sdpvar(24,1);%储能放电 Pch=sdpvar(24,1);%储能充电 Pc1=sdpvar(24,1);%一类车充电功率 Pc2=sdpvar(24,1);%二类车充电功率 Pc3=sdpvar(24,1);%三类车充电功率 S=sdpvar(24,1);%储荷容量 for t=2:24 S(t)=S(t-1)+0.9*Pch(t)-Pdis(t)/0.9; end %内层 CI=[sum(Pc1)==50*(0.9*24-9.6),sum(Pc2)==20*(0.9*24-9.6),sum(Pc3)==10*(0.9*24-9.6),Pc1>=0,Pc2>=0,Pc3>=0,Pc1<=50*3,Pc2<=20*3,Pc3<=10*3,Pc1(index1)==0,Pc2(index2)==0,Pc3(index3)==0];%电量需求约束 OI=sum(Ce.*(Pc1+Pc2+Pc3)); ops=sdpsettings('solver','gurobi','kkt.dualbounds',0); [K,details] = kkt(CI,OI,Ce,ops);%建立KKT系统,Ce为参量 %外层 CO=[lb<=Ce<=ub,mean(Ce)==0.5,Pb>=0,Ps_day<=Pdis,Pb_day>=0,Pb_day<=1000*z,Ps_day>=0,Ps_day<=1000*(1-z),Pch>=0,Pch<=1000*u,Pdis>=0,Pdis<=1000*(1-u)];%边界约束 CO=[CO,Pc1+Pc2+Pc3+Pch-Pdis==Pb+Pb_day-Ps_day];%能量平衡 CO=[CO,sum(0.9*Pch-Pdis/0.9)==0,S(24)==2500,S>=0,S<=5000];%SOC约束 OO=-(details.b'*details.dual+details.f'*details.dualeq)+sum(price_s.*Ps_day-price_day_ahead.*Pb-price_b.*Pb_day);%目标函数 optimize([K,CI,CO,boundingbox([CI,CO]),details.dual<=1],-OO) Ce=value(Ce);%电价 Pb=value(Pb);%日前购电 Pb_day=value(Pb_day);%实时购电 Ps_day=value(Ps_day);%实时购电 Pdis=value(Pdis);%储能放电 Pch=value( Pch);%储能充电 Pb_day=value(Pb_day);%实时购电 Pb_day=value(Pb_day);%实时购电 Pc1=value(Pc1);%一类车充电功率 Pc2=value(Pc2);%二类车充电功率 Pc3=value(Pc3);%三类车充电功率 S=value(S);%储荷容量 figure(1) plot(Pc1,'-*','linewidth',1.5) grid hold on plot(Pc2,'-*','linewidth',1.5) hold on plot(Pc3,'-*','linewidth',1.5) title('三类电动汽车充电功率') legend('类型1','类型2','类型3') xlabel('时间') ylabel('功率') figure(2) bar(Pdis,0.5,'linewidth',0.01) grid hold on bar(Pch,0.5,'linewidth',0.01) hold on plot(S,'-*','linewidth',1.5) axis([0.5 24
06-11

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值