SDKD 2021 C1 7th Round

A - Creating a Character

  • 签到题
#include <iostream>
#include <cstdio>
using namespace std;
int t,a,b,c;
int main()
{
    cin>>t;
    while(t--)
    {
        int ans=0;
        scanf("%d%d%d",&a,&b,&c);
        int cha=a+c-b;
        if(cha>0)
        {
            ans++;
            int tmp=(cha/2-(cha%2==0));
            ans+=min(tmp,c);
        }
        cout<<ans<<endl;
    }
    return 0;
}

B - Zmei Gorynich

  • 签到题
  • 求最少几下把龙砍死,贪心,斩杀线以上用差值高的,最后一下用伤害高的。特判的答案没输出换行,白给两发WA。
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int t,n,x;
int main()
{
    cin>>t;
    while(t--)
    {
        int def=0,cha=0;
        scanf("%d%d",&n,&x);
        for(int i=1,d,h;i<=n;i++)
        {
            scanf("%d%d",&d,&h);
            def=max(def,d);
            cha=max(cha,d-h);
        }
        if(cha<=0&&def<x)
        {
            cout<<-1<<endl;
            continue;
        }
        if(def>=x)
        {
            cout<<1<<endl;
            continue;
        }
        int tmp=(x-def)/cha+((x-def)%cha!=0);
        cout<<tmp+1<<endl;
    }
    return 0;
}

C - The Battle of Chibi

  • 签到题
  • 很容易想到朴素的dp,dp(i,j)表示当前在i选取了j个数的方案数,n^2的状态,每次n的转移,总时间复杂度O(n ^ 3),但是不难发现对于每个状态的转移实际上是一个离散化后的区间求和(甚至是个前缀和),所以数据结构维护一下就好了。
  • 树状数组可,这题卡常,不能用map,其实可以进一步降低常数,把对离散化的位置查询降为O(1)。线段树常数大些,不知道行不行。
  • 状态的定义有时为了方便还是需要认为的增加含义。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <map>
#include <cstring>
using namespace std;
const int mod = 1000000007;
int t,n,m,f[1005][1005],a[1005],tree[1005],b[1005],num;
int lowbit(int x)
{
    return x&-x;
}
void addss(int x,int k)
{
    while(x<=n)
    {
        tree[x]=(tree[x]+k)%mod;
        x+=lowbit(x);
    }
}
int query(int x)
{
    int ans=0;
    while(x>0)
    {
        ans=(ans+tree[x])%mod;
        x-=lowbit(x);
    }
    return ans;
}
int main()
{
    cin>>t;
    while(t--)
    {
        num++;
        int cnt=0;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            b[i]=a[i];
            f[i][1]=1;
        }
        sort(b+1,b+1+n);
        cnt=unique(b+1,b+n+1)-b-1;
        for(int i=2;i<=m;i++)
        {
            memset(tree,0,sizeof(tree));
            for(int j=1;j<=i-1;j++)
            {
                if(f[j][i-1])
                {
                    int pos=lower_bound(b+1,b+1+cnt,a[j])-b;
                    addss(pos,f[j][i-1]);
                }

            }

            for(int j=i;j<=n;j++)
            {
                int pos=lower_bound(b+1,b+1+cnt,a[j])-b;
                f[j][i]=query(pos-1)%mod;
                if(f[j][i-1])
                    addss(pos,f[j][i-1]);

            }
        }
        int ans=0;
        for(int i=1;i<=n;i++)
        ans=(ans%mod+f[i][m]%mod)%mod;
        printf("Case #%d: %d\n",num,ans);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
               f[i][j]=0;
    }
    return 0;
}

D - Hanoi tower

  • 汉诺塔问题中求当三个竹子套的一样多时所需步数。
  • 打表找规律,我也瞪不出啥规律,这方面一直不行,c++写需要高精。python好像可以写的又短又好看。
  • 下学期要学好python
a = [0]*105;
a[1] = 2
a[2] = 9
deta = 97
for i in range(3,103):
    if i%2==1:
        a[i] = a[i-1]*4+2
    else:
        a[i] = a[i-1]+deta
        deta = 15*deta + deta-15
#print(a)
#n = int(int(input())/3)
In  = open("input.txt","r")
Out = open("output.txt","w")
n = int(int(In.read())/3)
Out.write(str(a[n]))
#print(a[n])

E - Invoker

  • 签到题
  • 其实是个难度较低的线性dp,但是题意太容易搞错了。
  • DOTA2中要打出技能需要三个元素然后需要一个R,手头上只能保留三个元素(R不算),求按顺序打出给定技能所需要添加的最少元素数,当有三个元素时再添加元素将删除最开始添加的那个元素。
  • 当前持有的元素只有添加顺序的先后,但是打技能的时候可以随意(每个元素只算一次),比如当前为EWE,是可以打出WEE的。
  • dp(i,j),要打第i个技能时所持元素有六种情况(3的排列),dp(i,j)=min(dp(i-1,k)+此情况需添加元素数),1<=j<=6,1<=k<=6。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
char s[100005],nw[5];
int dp[100005][10];
string ss[105];
int gt(char a)
{
    return a-'A';
}
int solve(int a,int b)
{
    int ans=1e9;
    char nw[5],nww[5];
    if(b==1||b==2)
        nw[0]=ss[gt(s[a])][0];
    if(b==3||b==4)
        nw[0]=ss[gt(s[a])][1];
    if(b==5||b==6)
        nw[0]=ss[gt(s[a])][2];
    if(b==3||b==5)
        nw[1]=ss[gt(s[a])][0];
    if(b==1||b==6)
        nw[1]=ss[gt(s[a])][1];
    if(b==2||b==4)
        nw[1]=ss[gt(s[a])][2];
    int tot=ss[gt(s[a])][0]+ss[gt(s[a])][1]+ss[gt(s[a])][2];
    nw[2]=tot-nw[0]-nw[1];
    for(int i=1;i<=6;i++)
    {
        if(i==1||i==2)
            nww[0]=ss[gt(s[a-1])][0];
        if(i==3||i==4)
            nww[0]=ss[gt(s[a-1])][1];
        if(i==5||i==6)
            nww[0]=ss[gt(s[a-1])][2];
        if(i==3||i==5)
            nww[1]=ss[gt(s[a-1])][0];
        if(i==1||i==6)
            nww[1]=ss[gt(s[a-1])][1];
        if(i==2||i==4)
            nww[1]=ss[gt(s[a-1])][2];
        tot=ss[gt(s[a-1])][0]+ss[gt(s[a-1])][1]+ss[gt(s[a-1])][2];
        nww[2]=tot-nww[0]-nww[1];
        if(nw[0]==nww[0]&&nw[1]==nww[1]&&nw[2]==nww[2])
            ans=min(ans,dp[a-1][i]+1);
        else
            if(nww[1]==nw[0]&&nww[2]==nw[1])
                ans=min(ans,dp[a-1][i]+2);
        else
            if(nww[2]==nw[0])
                ans=min(ans,dp[a-1][i]+3);
        else
            ans=min(ans,dp[a-1][i]+4);
    }
    return ans;
}
int main()
{
    ss['Y'-'A']="QQQ";
    ss['V'-'A']="QQW";
    ss['G'-'A']="QQE";
    ss['C'-'A']="WWW";
    ss['X'-'A']="QWW";
    ss['Z'-'A']="WWE";
    ss['T'-'A']="EEE";
    ss['F'-'A']="QEE";
    ss['D'-'A']="WEE";
    ss['B'-'A']="QWE";
    scanf("%s",s);
    int len=strlen(s);
    for(int i=1;i<=6;i++)
        dp[0][i]=4;
    for(int i=1;i<len;i++)
    {
        for(int j=1;j<=6;j++)
        {
            dp[i][j]=solve(i,j);
        }
    }
    int minn=1e9;
    for(int i=1;i<=6;i++)
        minn=min(minn,dp[len-1][i]);
    cout<<minn;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哈希表扁豆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值