Loading

黑题首杀——大佬

这是Noip模拟四的T4,当时一看题目就知其不凡

果然,竟然是我OI生涯第一个要面对的黑题

不过吐槽一下,做题就做题吧,你把题面出的这么逗逼很难让人读题的时候不笑出声。。。。

豆比传送门

正解(六维信队)

没有烧脑的思维含量,只有永恒的代码能力;

要想考试碾压标程,还是得看我们信队!!(尽管本人信队菜展了)

单单几行得满自己想要的最多的分,半个小时敲出理想远方。。。。。。

(不知道有没有广告费呢?)

引借一下zxs童鞋的码码,供ID为wsn的mzs童鞋学习:

 1 bool dp(int ti,int m,int f,int l,int c,int num)
 2 {
 3     if(!c)  return 1;
 4     if(c<0) return 0;
 5     if(ti>n)   return 0;
 6     m-=a[ti];
 7     if(m<0) return 0;
 8     if(dp(ti+1,m,f,l,c-1,num))  return 1;
 9     if(dp(ti+1,min(mc,m+w[ti]),f,l,c,num))  return 1;
10     if(dp(ti+1,m,f,l+1,c,num)) return 1;
11     if(dp(ti+1,m,f*l,l,c,num))  return 1;
12     if(num<2&&dp(ti+1,m,1,0,c-f,num+1)) return 1;
13     return 0;
14 }
View Code

现在,然我们瞧一瞧满分思路

通过审题,我们可以知道,每天辣鸡只会使用五个中的一个技能。

而我们可以发现,怼darklao与刷水题可以分开。

于是情况可以分为两个且唯一关联就是时间day,总共30天(样例里)。于是:

方案一:水题续命

称之续命,是要找到辣鸡最少刷几天水题保证自己不死。f[i][j]表示在第i天自信值为j的情况下刷水题的天数。 则可以得到状态转移方程:

不刷水题:

    f[i][j-a[i]]=max(f[i][j-a[i]],f[i-1][j]+1)

刷水题:

    int J=min(j-a[i]+w[i],mc);
    f[i][J]=max(f[i-1][j],f[i][J]);

方案二:怒怼大佬

保了自己命之后就可以开始怼大佬了!!

那么注意到只能够开两次大,则需要分成几种不同的情况:

1.一次不开就可以干掉

2.开一次可以干掉

3.大招全开

但在干这些事之前,我们需要把辣鸡的每天可能的等级,威力,天数存起来,并且注意去重。如果不去重,会导致,嘲讽值和天数多次一样的话,会导致最后计算三种情况时,将一天算成多天

那么,剩下的就看咱们的English到不到位了(尽管wsn用了些许汉语拼音,而且语法不太正确。。。)

 1 #include<bits/stdc++.h>
 2 #define int long long
 3 #define Day second
 4 #define Attack first
 5 using namespace std;
 6 inline int read(){
 7     int x=0,f=1; char ch=getchar();
 8     while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); }
 9     while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
10     return x*f;
11 }
12 const int NN=105,momo=1e6+7; 
13 int n,m,mc,a[NN],w[NN],C[NN];
14 int day,f[NN][NN];
15 struct MZS{ int up_day,F,L; };//sign the level_up day and the attack and the level
16 pair<int,int> zu[1000010]; int cnt;
17 int dalao_Cmax;
18 struct HASH{
19     struct node{int x,y,next;}e[1000010];int r[1000010],tot;
20     inline void add(int x,int y){//add to check repeat
21         int pw=(1ll*x*131+y)%momo;
22         e[++tot]=(node){x,y,r[pw]};
23         r[pw]=tot;
24     }
25     inline bool check(int x,int y){//whether repeat or not
26         int pw=(1ll*x*131+y)%momo;
27         for(int i=r[pw];i;i=e[i].next)
28             if(e[i].x==x&&e[i].y==y) return true;//find have repeat line
29         return false;//not repeat
30     }
31 }Map;
32 inline void DAY(){
33     for(int i=1;i<=n;i++)//day
34         for(int j=a[i];j<=mc;j++)//yourself confidence
35         {
36             f[i][j-a[i]]=max(f[i][j-a[i]],f[i-1][j]+1);//only heat by darklao
37             int J=min(j-a[i]+w[i],mc);//make sure that your confidence is not over_added
38             f[i][J]=max(f[i-1][j],f[i][J]);//do some water problem and heat by darklao
39             //also the maxn day you can attack darklao
40         }
41     for(int i=1;i<=n;i++)
42         for(int j=1;j<=mc;j++)
43             day=max(day,f[i][j]);//find the day that you can do minn(water problems)
44 }
45 inline void DUI(){
46     queue<MZS> Q;//use to record the day you improve yourself,your attack_value and level
47     Q.push((MZS){1,1,0});//give the queue a start value
48     while(!Q.empty()){
49         MZS q=Q.front(); Q.pop();
50         if(q.up_day==day) continue;
51         Q.push((MZS){q.up_day+1,q.F,q.L+1});//level up
52         if(q.L>1&&1ll*q.F*q.L<=1ll*dalao_Cmax&&!Map.check(q.F*q.L,q.up_day+1)){
53             //make sure one attack and level only record once
54             Q.push((MZS){q.up_day+1,q.F*q.L,q.L});//attack_value up
55             zu[++cnt]=make_pair(q.F*q.L,q.up_day+1);//record the level and attack situaton
56             Map.add(q.F*q.L,q.up_day+1);////record the level and attack situaton
57         }
58     }
59 }
60 namespace WSN{
61     inline int main(){
62         n=read(),m=read(),mc=read();
63         for(int i=1;i<=n;i++) a[i]=read();
64         for(int i=1;i<=n;i++) w[i]=read();
65         for(int i=1;i<=m;i++) C[i]=read(),dalao_Cmax=max(dalao_Cmax,C[i]);
66         DAY();  DUI();
67         sort(zu+1,zu+cnt+1);//up_sort
68         for(int i=1;i<=m;i++){
69             if(C[i]<=day) {puts("1"); continue; }//not to Dui darklao,use "1" to kill him
70             bool flag=0; int minn=1e9;
71             for(int j=cnt,k=1;j;j--){//two signed mark to ensure the range and bool
72                 while(k<cnt && zu[k].Attack+zu[j].Attack<=C[i])
73                 //before k to the end ,the sum of attack is less than the confidence od darklao
74                     minn=min(minn,zu[k].Day-zu[k].Attack),k++;//use mark "k" to go through the "zu"
75                     //find the minn of "cha zhi"
76                 if(minn<=(day-zu[j].Day)-(C[i]-zu[j].Attack))//Dui twice
77                 {flag=1; break;}//use the "cha zhi" in while to judge this darklao 
78                 if(zu[j].Attack<=C[i]&&C[i]-zu[j].Attack<=day-zu[j].Day)//Dui once
79                 {flag=1; break;}//
80             }
81             puts(flag? "1": "0");
82         }
83         return 0;
84     }
85 }
86 signed main(){return WSN::main();}
View Code

就到这里吧,第一道黑题没想到题面这么豆比。。。。。

posted @ 2021-06-16 19:02  雪域亡魂  阅读(131)  评论(0)    收藏  举报