11.2考试爆炸记

真·玄学出奇迹
160暴力→220玄学成绩
简单说一说四道题
(1)活动安排
求最多区间覆盖集

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
using namespace std;
inline int read(){
    int i=0,f=1;
    char ch;
    for(ch=getchar();!isdigit(ch);ch=getchar())
        if(ch=='-') f=-1;
    for(;isdigit(ch);ch=getchar())
        i=(i<<3)+(i<<1)+(ch^48);
    return i*f;
}
int buf[1024];
inline void write(int x){
    if(!x){putchar('0');return ;}
    if(x<0){putchar('-');x=-x;}
    while(x){buf[++buf[0]]=x%10,x/=10;}
    while(buf[0]) putchar(buf[buf[0]--]+48);
    return ;
}
#define stan 111111
struct aaa{
    int s,t;
}a[stan];
int n,ed,ans;
bool cmp(aaa a,aaa b){
    if(a.t!=b.t) return a.t<b.t;
    else return a.s<b.s;
}
signed main(){
    n=read();
    for(int i=1;i<=n;++i){
        a[i].s=read()*60+read();
        a[i].t=read()*60+read();
    }
    sort(a+1,a+n+1,cmp);
    ed=-1;
    for(int i=1;i<=n;++i)
        if(ed<=a[i].s)
            ++ans,ed=a[i].t;
    write(ans);
    return 0;
}

(2)最佳序列
二分平均值后单调队列判断平均值是否合法

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
#include<deque>
#define int long long
#define eps 1e-6
using namespace std;
inline int read(){
    int i=0,f=1;
    char ch;
    for(ch=getchar();!isdigit(ch);ch=getchar())
        if(ch=='-') f=-1;
    for(;isdigit(ch);ch=getchar())
        i=(i<<3)+(i<<1)+(ch^48);
    return i*f;
}
int buf[1024];
inline void write(int x){
    if(!x){putchar('0');return ;}
    if(x<0){putchar('-');x=-x;}
    while(x){buf[++buf[0]]=x%10,x/=10;}
    while(buf[0]) putchar(buf[buf[0]--]+48);
    return ;
}
#define stan 222222 
int n,l,r;
double a[stan],sum[stan],ll,rr,mid;
bool check(double val){
    for(int i=1;i<=n;++i)
        sum[i]=a[i]-val;
    for(int i=1;i<=n;++i)
        sum[i]+=sum[i-1];
    deque<int>que;
    for(int i=l;i<=n;++i){
        while(!que.empty()&&sum[que.back()]>sum[i-l]) que.pop_back();
        que.push_back(i-l);
        if(sum[i]>sum[que.front()]) return true;
        while(!que.empty()&&que.front()<=i-r) que.pop_front();
    }
    return false;
}
signed main(){
    n=read();l=read();r=read();
    for(int i=1;i<=n;++i)
        a[i]=read();
    ll=0.0000;rr=1000000;
    while(rr-ll>eps){
        mid=(ll+rr)*0.5;
        if(check(mid)) ll=mid;
        else rr=mid;
    }
    printf("%.4f",(ll+rr)*0.5);
    return 0;
}

(3)回文子串
其实是个 n4 DP,各种花式边界防炸

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
using namespace std;
inline int read(){
    int i=0,f=1;
    char ch;
    for(ch=getchar();!isdigit(ch);ch=getchar())
        if(ch=='-') f=-1;
    for(;isdigit(ch);ch=getchar())
        i=(i<<3)+(i<<1)+(ch^48);
    return i*f;
}
int buf[1024];
inline void write(int x){
    if(!x){putchar('0');return ;}
    if(x<0){putchar('-');x=-x;}
    while(x){buf[++buf[0]]=x%10,x/=10;}
    while(buf[0]) putchar(buf[buf[0]--]+48);
    return ;
}
#define stan 55
int f[stan][stan][stan][stan],len1,len2,a,b,c,d,ans;
char s[stan],t[stan];
signed main(){
    scanf("%s%s",s+1,t+1);
    len1=strlen(s+1);
    len2=strlen(t+1);
    for(register int i=1;i<=len1+1;++i)
        for(register int j=1;j<=len2+1;++j)
            for(register int k=len1;k>=0;--k)
                for(register int l=len2;l>=0;--l){
                    a=i;b=j;c=k;d=l;
                    if(a<c&&(s[a]==s[c])&&f[a+1][b][c-1][d]<f[a][b][c][d]+2)
                        f[a+1][b][c-1][d]=f[a][b][c][d]+2;
                    if(b<d&&(t[b]==t[d])&&f[a][b+1][c][d-1]<f[a][b][c][d]+2)
                        f[a][b+1][c][d-1]=f[a][b][c][d]+2;
                    if(a<=c&&b<=d&&(s[a]==t[d])&&f[a+1][b][c][d-1]<f[a][b][c][d]+2)
                        f[a+1][b][c][d-1]=f[a][b][c][d]+2;
                    if(a<=c&&b<=d&&(t[b]==s[c])&&f[a][b+1][c-1][d]<f[a][b][c][d]+2)
                        f[a][b+1][c-1][d]=f[a][b][c][d]+2;
                }
    for(register int i=1;i<=len1+1;++i)
        for(register int j=1;j<=len2+1;++j)
            for(register int k=len1;k>=0;--k)
                for(register int l=len2;l>=0;--l){
                    a=i;b=j;c=k;d=l;
                    if((a==c&&b>d)||(a>c&&b==d)) ans=max(ans,f[a][b][c][d]+1);
                    else if(a>c&&b>d) ans=max(ans,f[a][b][c][d]);
                }
    write(ans);
    return 0;
}

(4)赌博游戏
比第三题简单

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
using namespace std;
inline int read(){
    int i=0,f=1;
    char ch;
    for(ch=getchar();!isdigit(ch);ch=getchar())
        if(ch=='-') f=-1;
    for(;isdigit(ch);ch=getchar())
        i=(i<<3)+(i<<1)+(ch^48);
    return i*f;
}
int buf[1024];
inline void write(int x){
    if(!x){putchar('0');return ;}
    if(x<0){putchar('-');x=-x;}
    while(x){buf[++buf[0]]=x%10,x/=10;}
    while(buf[0]) putchar(buf[buf[0]--]+48);
    return ;
}
#define stan 55
double f[stan*stan][stan][2],base;
int n,m,v,sum;
signed main(){
    n=read();m=read();v=read();sum=read();
    if(n==1){
        if(v==sum){
            puts("1.00000000");
            return 0;
        }else{
            puts("0.00000000");
            return 0;
        }
    }
    for(int i=1;i<=m;++i)
        if(i!=v) f[i][1][0]=1.0/m;
        else f[i][1][1]=1.0/m;
    for(int i=1;i<n;++i){
        for(int j=1;j<=m*i;++j)
            for(int k=1;k<=m;++k)
                if(k!=v){
                    f[j+k][i+1][0]+=f[j][i][0]*1.0/m;
                    f[j+k][i+1][1]+=f[j][i][1]*1.0/m;
                }else{
                    f[j+k][i+1][1]+=(f[j][i][0]+f[j][i][1])*1.0/m;
                }
    }
    for(int i=1;i<=n*m;++i)
        base+=f[i][n][1];
    printf("%.8f",f[sum][n][1]/base);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值