bzoj 5105~5108 垃圾题解

前言

比赛AK了(虽然是div2

T1:

lcm不解释。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#define LL long long
using namespace std;
LL gcd(LL a,LL b)
{
    if(a==0) return b;
    return gcd(b%a,a);
}
LL lcm(LL a,LL b) {return a/gcd(a,b)*b;}
int main()
{
    LL a,b,c;scanf("%lld %lld %lld",&a,&b,&c);
    printf("%lld",lcm(a,lcm(b,c)));
}

T2:

二分傻逼题,注意下边界。

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
#define LL long long
using namespace std;
const LL inf=1000000000000000000;
LL up(LL a,LL b) {return a%b==0?a/b:a/b+1;}
LL n,m,L;
LL h[200010],a[200010];
bool check(LL x)
{
    LL tot=0;
    for(int i=1;i<=n;i++)
    {
        if(up(inf,a[i])<=x) return true;
        LL tmp=a[i]*x;
        if(a[i]*x+h[i]<L) continue;
        if(m-tot<=a[i]*x+h[i]) return true;
        tot+=(a[i]*x+h[i]);
    }
    return false;
}
int main()
{
    scanf("%lld %lld %lld",&n,&m,&L);
    for(LL i=1;i<=n;i++) scanf("%lld",&h[i]);
    for(LL i=1;i<=n;i++) scanf("%lld",&a[i]);
    LL l=0,r=inf,ans;
    while(l<=r)
    {
        LL mid=(l+r)/2;
        if(check(mid)) r=mid-1,ans=mid;
        else l=mid+1;
    }
    printf("%lld",ans);
}

T3:

显然dp。
f[i][j] 表示一串前i个,二串前j个的最大值。
好像不能转移,所以加一维0,1,2,分别表示最后都不是空格,一串空格结尾,二串空格结尾的最大值。(显然不存在都以空格结尾)。然后就可以转移了。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#define LL long long
using namespace std;
char s[3010],s1[3010];
LL map[3010][3010],A,B;
LL f[3010][3010][3];//0末尾都没空格,1一串有,2而串有
LL qs(char c)
{
    if(c=='A') return 1;
    if(c=='T') return 2;
    if(c=='G') return 3;
    if(c=='C') return 4;
}
int main()
{
    scanf("%s %s",s+1,s1+1);
    for(LL i=1;i<=4;i++)
        for(LL j=1;j<=4;j++) scanf("%lld",&map[i][j]);
    scanf("%lld %lld",&A,&B);
    LL n=strlen(s+1),m=strlen(s1+1);
    memset(f,-63,sizeof(f));
    //f[0][0][1]=f[0][0][2]=(-(1LL<<60));
    f[0][0][0]=0;
    for(LL i=0;i<=n;i++)
        for(LL j=0;j<=m;j++)
        {
            if(i+j==0) continue;
            LL a=qs(s[i]),b=qs(s1[j]);
            if(i!=0&&j!=0) f[i][j][0]=map[a][b]+max(f[i-1][j-1][0],max(f[i-1][j-1][1],f[i-1][j-1][2]));
            if(j!=0) f[i][j][1]=max(f[i][j-1][0]-A,max(f[i][j-1][1]-B,f[i][j-1][2]-A));
            if(i!=0) f[i][j][2]=max(f[i-1][j][0]-A,max(f[i-1][j][1]-A,f[i-1][j][2]-B));
        }
    printf("%lld\n",max(f[n][m][0],max(f[n][m][1],f[n][m][2])));
    //printf("%lld %lld %lld",f[n][m][0],f[n][m][1],f[n][m][2]);
}

T4:

容易发现n没什么卵用……
因为对于没有钦定的地方,显然可以让b数组对应位置上都是0。
但是对于一段钦定位置前的位置,不一定填0优。
所以就按位考虑填0,1的代价,取较小值就可以了。
code:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
struct node{
    int x,c;
}a[100010];
int n,m,c[2][35];
bool cmp(node a,node b) {return a.x<b.x;}
LL solve(int l,int r)
{
    LL ans=0;int tmp=0;
    if(a[l].x==1) for(int i=l;i<=r;i++) tmp^=a[i].c,ans+=(LL)tmp;
    else
    {
        memset(c,0,sizeof(c));
        for(int i=0;i<=30;i++)
        {
            for(int k=0;k<=1;k++)
            {
                int tmp=(k<<i);c[k][i]+=(tmp!=0);
                for(int j=l;j<=r;j++)
                    tmp^=(a[j].c&(1<<i)),c[k][i]+=(tmp!=0);
            }
            ans+=(LL)(1<<i)*(LL)min(c[0][i],c[1][i]);
        }
    }
    return ans;
}
int main()
{
    scanf("%d %d",&n,&m);
    for(int i=1;i<=m;i++) scanf("%d %d",&a[i].x,&a[i].c);
    sort(a+1,a+m+1,cmp);
    int p=1;
    LL ans=0;
    while(p<=m)
    {
        int t=p;
        while(p<m&&a[p].x+1==a[p+1].x) p++;
        ans+=solve(t,p);
        p++;
    }
    printf("%lld",ans);
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值