模拟赛 10-14考试再次翻车记

10-14 考试

7点开始考试,第一题傻逼题啊,直接取模过程中加上商就可以了,切掉切掉。

1、光剑
(sword.pas/c/cpp)
【题目描述】
小林和亮亮各有一把光剑,长度分别为 a 和 b,他们拿光剑进行比试。每一
回合,长光剑会砍向短光剑,砍完后,短光剑完好无损,而长光剑则被截成两段,
被截去的长度恰好等于短光剑的长度。若两把光剑长度相等,则比试结束。请问
小林和亮亮将比试多少回合?
【输入格式】
第一行一个整数 T,表示数据组数。
接下来 T 行每行两个正整数 a,b,表示初始状态光剑的长度。
【输出格式】
每组数据输出一个整数,表示能进行几个回合的比试。
【样例输入】
3
1 8
3 7
6 6
【样例输出】
7
4
0
【数据规模】
对于 40%的数据,0 < a,b <= 1000, 1 <= T <= 20;
对于 100%的数据,0 < a,b <= 10^18,1 <= T <= 1000。

code:

#include<iostream>
#include<cstdio>
#define int long long
using namespace std;
inline int read(){
    int sum=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0';ch=getchar();}
    return sum*f;
}
int t,a,b,ans;
long long work(long long x, long long y){
    if(x<y)swap(x, y);
    if(y==1)return x-1;
    if(x==y)return 0;
    if(y==0)return -1;
    else return work(y,x%y)+x/y;
}
signed main(){
    freopen("sword.in","r",stdin);
    freopen("sword.out","w",stdout);
    t=read();
    for (int i=1;i<=t;i++){
        long long x, y;
        x=read();y=read();
        printf("%lld\n",work(x, y));
    }
    fclose(stdin);
    fclose(stdout);
    return 0;
}

7点25开始看T2,第一眼感觉很恶心啊,先不管打一个\(n^5\)的暴搜再说。

打完暴搜立马就想起来昨天ZAGER出的T2,\(meeting  in  the  middle\) 啊,先搜前三层,再搜后两层,然后lower_bound找相反数就行了,这就完了。

2、化零
(zero.pas/c/cpp)
【题目描述】
小林拥有 2 个集合,亮亮拥有 3 个集合,这五个集合大小相等,且集合中包
含的都是整数。现在他们两个要进行心算比赛。比赛的规则是,将这五个集合放
在一起,谁能先从每个集合中各选一个数,使得选出的五个数之和为 0,谁就获
得胜利。由于这五个集合都不小,而小林和亮亮事先并不知道是否能存在这样的
五个数,因此他们决定先把五个集合都交给你,由你来编程判断是否存在符合条
件的五个数。
【输入格式】
第一行一个整数 N,表示集合的大小。
接下来五行每行 N 个整数,表示这五个集合内的元素。
【输出格式】
如果能找到符合条件的五个数,则输出“YES”,否则输出“NO”。
【样例输入】
3
1 -2 9
-1 2 1
-3 5 1
-1 7 6
-4 -1 -7
【样例输出】
YES
【数据规模】
对于 30%的数据,1 <= N <= 20;
对于 50%的数据,1 <= N <= 100;
对于 100%的数据,1 <= N <= 200,-10^8 <= a[i] <= 10^8,a[i]为集合中元素

code:

#include<iostream>
#include<cstdio>
#include<algorithm>
#define int long long
using namespace std;
const int wx=8000017;
inline int read(){
    int sum=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0';ch=getchar();}
    return sum*f;
}
int a[wx],b[wx];
int s[70][4170];
int cnt,tot,num,n;
void dfs(int step,int num){
    if(step>=4){
        a[++cnt]=num;
        return;
    }
    for(int i=1;i<=n;i++){
        dfs(step+1,num+s[step][i]);
    }
}
void DFS(int step,int num){
    if(step>=3){
        b[++tot]=num;
        return;
    }
    for(int i=1;i<=n;i++){
        DFS(step+1,num+s[step+3][i]);
    }
}
signed main(){
    freopen("zero.in","r",stdin);
    freopen("zero.out","w",stdout);
    n=read();
    for(int i=1;i<=5;i++){
        for(int j=1;j<=n;j++){
            s[i][j]=read();
        }
    }
    dfs(1,0);
    DFS(1,0);
    sort(a+1,a+1+cnt);
    for(int i=1;i<=tot;i++){
        int tmp=lower_bound(a+1,a+1+cnt,-b[i])-a;
        if(a[tmp]==-b[i]&&tmp<=cnt&&tmp>=1){
            printf("YES\n");
            return 0;
        }
    }
    printf("NO\n");
    fclose(stdin);
    fclose(stdout);
    return 0;
}

八点开始肝T3,看起来好难啊,鬼特么2048,不会。

但肯定是DP啊,瞎鸡儿设状态吧,但是感觉复杂度不太对劲啊,,二进制拆位走起来,溜了溜了。

3、2048
(2048.pas/c/cpp)
【题目描述】
小林和亮亮最近正在重温 2048 这款游戏。由于他们的游戏水平高超,觉得
没有什么挑战性,于是决定自己设计一款类似的游戏。
他们设计的游戏中,数字排成了一个线性的序列,每次玩家可以将序列中任
意两个相同的数 a 合并,成为一个新的数 2*a,当合并出 2048 时游戏即获得胜
利。设计完后,他们发现这个游戏比原来的版本更加简单了,于是他们就开始计
算,对于一个给定的长度为 n 的序列,它共有多少子序列可以合并出 2048。请
给出这个数模 998244353 后的值。
【输入格式】
第一行有一个整数 n。
第二行 n 个整数 Ai,表示数列中的数。
【输出格式】
一个整数,即为所求的答案。
【样例输入】
2
2048 2048
【样例输出】
3
【数据规模】
对于 40%的数据,n <= 20;
对于 70%的数据,n <= 500;
对于 100%的数据,1 <= n <= 100000,1 <= Ai <= 2048。

code:

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#define int long long
using namespace std;
const int wx=100017;
const int mod=998244353;
int n,cnt;
int a[20],flag[wx],WX[20];
int a1[wx],a2[wx],a3[wx];
int f[20][wx];
inline int read(){
    int sum=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0';ch=getchar();}
    return sum*f;
}
int ksm(int a,int b){
    int re=1;
    while(b){
        if(b&1)re=re*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return re;
}
void pre(){
    memset(flag,-1,sizeof(flag));
    for(int i=0;i<=11;i++){
        flag[1<<i]=i;
        WX[i]=2048/(1<<i);
    }
    a1[0]=1;
    for(int i=1;i<wx;i++)
        a1[i]=a1[i-1]*2%mod;
    a3[0]=a2[0]=1;
    for(int i=1;i<wx;i++){
        a3[i]=a3[i-1]*i%mod;
        a2[i]=ksm(a3[i],mod-2);
    }
}
void jia(int &a,int b){
    a+=b;
    if(a>=mod)a-=mod;
}
signed main()
{
    freopen("2048.in","r",stdin);
    freopen("2048.out","w",stdout);
    n=read();pre();
    for(int i=0;i<n;i++){
        int x;x=read();
        if(flag[x]==-1)cnt++;
        else a[flag[x]]++;
    }
    memset(f,0,sizeof f);
    int num=min(a[0],WX[0]);
    int sum=0,val;
    for(int i=0;i<=num;i++){
        val=a3[a[0]]*a2[i]%mod*a2[a[0]-i]%mod;
        f[0][i]=val;
        jia(sum,val);
    }
    if(WX[0]<a[0])
        f[0][WX[0]]=(f[0][WX[0]]+a1[a[0]]-sum+mod)%mod;
    for(int i=1;i<=11;i++){
        num=min(a[i],WX[i]);
        sum=0;
        for(int j=0;j<=num;j++){
            val=a3[a[i]]*a2[j]%mod*a2[a[i]-j]%mod;
            jia(sum,val);
            for(int k=0;k<=WX[i-1];k++)
                if(f[i-1][k]){
                    int temp=min(j+k/2,WX[i]);
                    jia(f[i][temp],val*f[i-1][k]%mod);
                }
        }
        if(a[i]>WX[i]){
            val=(a1[a[i]]-sum+mod)%mod;
            for(int j=0;j<=WX[i-1];j++)
                if(f[i-1][j])
                    jia(f[i][WX[i]],f[i-1][j]*val%mod);
        }
    }
    printf("%lld\n",f[11][1]*a1[cnt]%mod);
    return 0;
}

后记总结:
这场考试本来是AK的,但是因为种种原因才考了160分,难受。。。

第二题在debug的时候把\(8*10^6\)改成了\(1*10^6\),后四个点全都RE了,也是够傻逼了。。

第三题没写cstdio,直接暴库了,这可爱的dev,真好。

首先自己的题做的不错,但是还是细节上除了致命的问题,所以要像他们说的一样,把心沉下来,继续加油吧。

猜你喜欢

转载自www.cnblogs.com/wangxiaodai/p/9785666.html
今日推荐