初中信息奥赛模拟测试

初中信息奥赛模拟测试

终于是肯给 hzoi2024 整场模拟赛了。

题其实并不是很难。

但很有价值。

  1. ZEW 的游戏 (T2)

    显然是直接求斜率。

    注意判 \(0\)

    因为绝对值小于 \(1000\),可以直接用小数。

    正经应该是写个分数存,也不难实现。

    小数:

    CODE
    #include<bits/stdc++.h>
    using namespace std;
    const int N=405;
    int n;
    int cx[N],cy[N];
    unordered_set<double> c;
    inline double get(int xa,int ya,int xb,int yb){
        if(xa-xb==0) return 10000000000.0;
        return (ya-yb)*1.0/(xa-xb);
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d%d",&cx[i],&cy[i]);
            for(int j=1;j<i;j++) c.insert(get(cx[i],cy[i],cx[j],cy[j]));
        }
        cout<<c.size();
    }
    

    分数:

    CODE
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long llt;
    typedef unsigned long long ull;
    #define For(i,a,b,c) for(register int $L=a,$R=b,$C=c,$D=(0<=$C)-($C<0),i=$L;i*$D<=$R*$D;i+=$C)
    const int N=202,INF=0x3f3f3f3f;
    set<pair<int,int> > c;
    int cx[N],cy[N];
    
    namespace IO{
        template<typename T> inline void write(T x){
            static T st[45];T top=0;if(x<0)x=~x+1,putchar('-');
            do{st[top++]=x%10;}while(x/=10);while(top)putchar(st[--top]^48);
        }
        template<typename T> inline void read(T &x){
            char s=getchar();x=0;bool pd=false;while(s<'0'||'9'<s){if(s=='-') pd=true;s=getchar();}
            while('0'<=s&&s<='9'){x=(x<<1)+(x<<3)+(s^48),s=getchar();}if(pd) x=-x;
        }
    }
    namespace IO{
        template<typename T,typename... Args> inline void read(T& x,Args&... args){read(x);read(args...);}
        inline void write(const char c){putchar(c);}
        inline void write(const char *c){int len=strlen(c);For(i,0,len-1,1) putchar(c[i]);}
        template<typename T> inline void Write(T x){write(x);putchar(' ');}
        inline void Write(const char c){write(c);if(c!='\n') putchar(' ');}
        inline void Write(const char *c){write(c);if(c[strlen(c)-1]!='\n') putchar(' ');}
        template<typename T,typename... Args> inline void write(T x,Args... args){write(x);write(args...);}
        template<typename T,typename... Args> inline void Write(T x,Args... args){Write(x);Write(args...);}
    }
    using namespace IO;
    inline pair<int,int> get(int xa,int ya,int xb,int yb){
        int x=xa-xb,y=ya-yb,gd=__gcd(x,y);
        if(x==0) return make_pair(INF,1);
        return make_pair(y/gd,x/gd);
    }
    
    int main(){
    #ifndef ONLINE_JUDGE
        freopen("in_out/in.in","r",stdin);
        freopen("in_out/out.out","w",stdout);
    #endif
        int n;read(n);
        For(i,1,n,1){
            read(cx[i],cy[i]);
            For(j,1,i-1,1) c.insert(get(cx[i],cy[i],cx[j],cy[j]));
        }
        cout<<c.size();
    }
    
  2. ZEW 学分块 (T3)

    可以二分答案。

    虽然理论复杂度爆炸,但实际没卡到。

    正经做是双指针。

    感谢 The_shadow_dragon 指正

    也可以双指针。

    枚举二三块的边界,贪心维护一下一二块。

    前缀和要开 longlong 实际上也没卡

    CODE
    #include<bits/stdc++.h>
    using namespace std;
    const int N=5e6+5;
    int n,cu[N];
    long long qsum[N],ans=0x3f3f3f3f;
    inline long long Dis(int x,int y){
        return qsum[y]-qsum[x];
    }
    signed main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",cu+i),qsum[i]=qsum[i-1]+cu[i];
        int p=0;
        for(int i=1;i<=n;i++){
            while(p<=i&&abs(Dis(p,i)-Dis(0,p))>=abs(Dis(p+1,i)-Dis(0,p+1))) p++;
            ans=min(ans,max(Dis(0,p),max(Dis(p,i),Dis(i,n))));
        }
        printf("%lld",ans);
    }
    
  3. ZEW 玩 thd (T4)

    背包。

    显然是在最后补刀。

    考虑在第 \(i\) 个时人最多攻击几下,为容量。

    最少补的下数为代价。

    因为最后一下打掉 \(i\) 的话会使塔少攻击一次。

    所以代价加一。

    转移显然。

    因为容量是不确定的,最后要求 \(max\),因为可能没有转移到。

    CODE
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long llt;
    typedef unsigned long long ull;
    #define For(i,a,b,c) for(register int $L=a,$R=b,$C=c,$D=(0<=$C)-($C<0),i=$L;i*$D<=$R*$D;i+=$C)
    const int N=202,W=2e5+3;
    int dp[W],p,q,n,w[N],v[N],wt[N],t;
    
    namespace IO{
        template<typename T> inline void write(T x){
            static T st[45];T top=0;if(x<0)x=~x+1,putchar('-');
            do{st[top++]=x%10;}while(x/=10);while(top)putchar(st[--top]^48);
        }
        template<typename T> inline void read(T &x){
            char s=getchar();x=0;bool pd=false;while(s<'0'||'9'<s){if(s=='-') pd=true;s=getchar();}
            while('0'<=s&&s<='9'){x=(x<<1)+(x<<3)+(s^48),s=getchar();}if(pd) x=-x;
        }
    }
    namespace IO{
        template<typename T,typename... Args> inline void read(T& x,Args&... args){read(x);read(args...);}
        inline void write(const char c){putchar(c);}
        inline void write(const char *c){int len=strlen(c);For(i,0,len-1,1) putchar(c[i]);}
        template<typename T> inline void Write(T x){write(x);putchar(' ');}
        inline void Write(const char c){write(c);if(c!='\n') putchar(' ');}
        inline void Write(const char *c){write(c);if(c[strlen(c)-1]!='\n') putchar(' ');}
        template<typename T,typename... Args> inline void write(T x,Args... args){write(x);write(args...);}
        template<typename T,typename... Args> inline void Write(T x,Args... args){Write(x);Write(args...);}
    }
    using namespace IO;
    
    int main(){
    #ifndef ONLINE_JUDGE
        freopen("in_out/in.in","r",stdin);
        freopen("in_out/out.out","w",stdout);
    #endif
        read(p,q,n); wt[0]=1;
        For(i,1,n,1){
            int h;
            read(h,v[i]);h--;
            wt[i]=wt[i-1]+(h/q+1);
            w[i]=(h%q/p+2);
        }
        For(i,1,n,1)
            For(j,wt[i],w[i],-1)
                dp[j]=max(dp[j],dp[min(wt[i-1],j-w[i])]+v[i]);
        int ans=0;
        For(i,1,wt[n],1) ans=max(ans,dp[i]);
        printf("%d",ans);
    }
    
posted @ 2024-01-16 21:41  xrlong  阅读(83)  评论(2编辑  收藏  举报