zoukankan      html  css  js  c++  java
  • [ZOJ]ZOJ Monthly, January 2018

    solved 4

    rank 1

    题挺好的,就是没见过这么卡常的。。

    A(签到)

    题意:有n个盒子,每个盒子里都有若干AB两种糖,甲只能吃A,乙只能吃B,每次至少吃一个,最多把一个盒子里的吃光,没有糖之后就不能吃,吃掉最后一颗糖的获胜,问谁能获胜。

    显然一次吃一颗最优,谁的糖多谁赢。

    #include<bits/stdc++.h>
    using namespace std;
    
    #define rep(i,n) for(int i=1;i<=n;i++)
    #define LL long long 
    #define pii pair<int,int>
    #define pb push_back
    #define mp make_pair
    
    const int N =2e3+7;
    const int mod=1e9+7;
    
    int n,k;
    
    int main(){
        int t,x;
        cin>>t;
        while(t--){
            cin>>n;
            int s1=0,s2=0;
            rep(i,n){
                cin>>x;
                s1+=x;
            }
            rep(i,n){
                cin>>x;
                s2+=x;
            }
            if(s1>s2)cout<<"BaoBao"<<endl;
            else cout<<"DreamGrid"<<endl;
        }
    
    
    
        //system("pause");
    }
    View Code

    00:05(2A)

    E(线段树)

    题意:询问数列一段区间的乘积,支持区间乘法和区间乘方。

    比较裸的线段树,对两种操作打两个tag分别维护,由费马小定理推论: p是质数时,a^(n%(p-1))=a^n(%p)。对指数取模(p-1)即可。

    (函数不加inline还T,我写的常数这么大吗。。)

    #include<bits/stdc++.h>
    using namespace std;
    #define LL long long
    #define rep(i,n) for(int i=1;i<=n;i++)
    
    const int N=1e5+7;
    const int mod=1e9+7;
    
    int n,a[N],tree[N*4],tag1[N*4],tag2[N*4],len[N*4];
    
    inline void update(int node){
        tree[node]=1LL*tree[node<<1]*tree[node<<1|1]%mod;
    }
    
    inline int po(int x,int y){
        int res=1;
          while(y){
          if(y&1)res=1LL*res*x%mod;
          y>>=1;
          x=1LL*x*x%mod;
          }
          return res;
    }
    
    inline void maketag(int node,int v,int k){
        tree[node]=1LL*po(tree[node],k)*po(v,len[node])%mod;
        tag1[node]=1LL*po(tag1[node],k)*v%mod;
        tag2[node]=1LL*tag2[node]*k%(mod-1);
    }
    
    inline void push_down(int node){
        maketag(node<<1,tag1[node],tag2[node]);
        maketag(node<<1|1,tag1[node],tag2[node]);
        tag1[node]=tag2[node]=1;
    }
    
    inline int query(int node,int L,int R,int l,int r){
        if(l>R||r<L)return 1; 
        if(L>=l&&R<=r)return tree[node];
        push_down(node);
        int mid=(L+R)>>1;
        return 1LL*query(node<<1,L,mid,l,r)*query(node<<1|1,mid+1,R,l,r)%mod;
    }
    
    inline void change(int node,int L,int R,int l,int r,int v,int k){
        if(l>R||r<L)return;
        if(L>=l&&R<=r){
            maketag(node,v,k);
            return ;
        }
        if(tag1[node]!=1||tag2[node]!=1)push_down(node);
        int mid=(L+R)>>1;
        change(node<<1,L,mid,l,r,v,k);
        change(node<<1|1,mid+1,R,l,r,v,k);
        update(node);
    }
    
    void build(int node,int l,int r){
        tag1[node]=tag2[node]=1;
        len[node]=r-l+1;
        if(l==r){
            tree[node]=a[l];
            return;
        }
        int mid=(l+r)>>1;
        build(node<<1,l,mid);
        build(node<<1|1,mid+1,r);
        update(node);
    }
    
    int main()
    {
        int t,q;
        scanf("%d",&t);
        while(t--){
            scanf("%d%d",&n,&q);
    
            rep(i,n)scanf("%d",&a[i]);
    
            build(1,1,n);
    
            while(q--){
                int op,l,r,v;
                scanf("%d%d%d",&op,&l,&r);
                if(op==1){
                    scanf("%d",&v);
                    change(1,1,n,l,r,v,1);
                }
                if(op==2){
                    scanf("%d",&v);
                    change(1,1,n,l,r,1,v);
                }
                if(op==3){
                    printf("%d
    ",query(1,1,n,l,r));
                }
            }
        }
        //system("pause");
    }
    View Code

    02:07(3A)

    F(模拟)

    题意:给出一个多项式做分子和分母的分式,求分式趋近于x0的极限

    洛必达法则,一直求导到分子和分母不都为0即可。麻烦的其实只是读入。。注意输出格式。

    #include<bits/stdc++.h>
    using namespace std;
    #define LL long long
    #define rep(i,n) for(int i=1;i<=n;i++)
    
    const int N=1e5+7;
    const int mod=1e9+7;
    
    int num[2][10],x;
    
    LL gcd(LL a,LL b){
        if(!b)return a;
        return gcd(b,a%b);
    }
    
    void getit(string s,int k){
        int res=1,ex=-1;
        for(int i=0;i<s.size();i++){
            if(s[i]=='x'){
                ex=1;
            }
            else if(s[i]=='^'){
                ex=s[i+1]-'0';
                i++;
            }
            else if(s[i]=='-'){
                if(ex!=-1){
                    num[k][ex]=res;
                    res=1;
                    ex=-1;}
                res=-1;
            }
            else if(s[i]>='0'&&s[i]<='9')res*=s[i]-'0',ex=0;
            else {
                num[k][ex]=res;
                res=1;
                ex=-1;
            }
        }
            if(ex!=-1){
                num[k][ex]=res;
                res=1;
                ex=0;
           }
          // for(int i=0;i<=9;i++)cout<<num[k][i]<<" ";
           //cout<<endl;
    }
    
    LL getnum(int k){
        LL res=1;
        LL ans=0;
        for(int i=0;i<=9;i++){
            ans+=res*num[k][i];
            res*=x;
        } 
        return ans;
    }
    
    void change(int k){
        for(int i=0;i<9;i++){
            num[k][i]=num[k][i+1]*(i+1);
            num[k][i+1]=0;
        }
        //for(int i=0;i<=9;i++)cout<<num[k][i]<<" ";
        //cout<<endl;
    } 
    
    
    string s1,s2;
    
    int main(){
        int t;
    
        scanf("%d",&t);
        while(t--){
            memset(num,0,sizeof(num));
            cin>>s1>>s2>>x;
            getit(s1,0);
            getit(s2,1);
            while(getnum(0)==0&&getnum(1)==0){
                change(0);
                change(1);
            }
            if(getnum(1)==0)cout<<"INF"<<endl;
            else if(getnum(0)==0)cout<<0<<endl;
            else {
                LL g=gcd(abs(getnum(0)),abs(getnum(1)));
                if( (getnum(0)>0)!=(getnum(1)>0) )cout<<"-";
                if(abs(getnum(1))/g==1)cout<<abs(getnum(0))/g<<endl;
                else cout<<abs(getnum(0))/g<<"/"<<abs(getnum(1))/g<<endl;
            }
        }
    }
    View Code

    03:06(2A)

    J(暴力)

    题意:给出两个序列An,Bn,有多少对等长的子序列Ai-j和Bi-j之间的距离小于等于v,两个子序列的距离定义为 ∑ (|ai-bi|^p) (p<=3)

    暴力的做法是n^3枚举两个区间起点和最大长度,考虑优化。以Ai和Bj为起点时,因为距离公式的每一项都非负,显然最大长度至少是以Ai-1和Bj-1为起点是的最大长度减一。因此每次暴力的时候记录下最大长度和这一段的距离,之后就可以再次使用。因为区间右端点是单调递增的,也就是长度最多扩大n次。类似于双指针,可以证明复杂度是O(n^2)的。

    (不知道为什么时间卡的这么紧。。1e3还多组数据,改了无数遍才卡着过去了)

    #include<bits/stdc++.h>
    using namespace std;
    #define LL long long
    #define rep(i,n) for(int i=1;i<=n;i++)
    
    const int N=1005;
    LL a[N],b[N];
    
    int l[N][N];
    
    LL sum[N][N];
    
    LL n,v,p;
    
    inline LL f(int i,int j)
    {
        LL res=1,x=abs(a[i]-b[j]);
        rep(i,p)res*=x;
        return res;
    }
    int main()
    {
    
        int t;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%lld%lld%lld",&n,&v,&p);
            rep(i,n)scanf("%lld",&a[i]);
            rep(i,n) scanf("%lld",&b[i]);  
            LL ans=0;
            rep(i,n)
            {
                rep(j,n)
                {
                    LL now=sum[i-1][j-1]-f(i-1,j-1);
                    int k;
                    for(k=l[i-1][j-1]-1; i+k<=n&&j+k<=n; k++)
                    {
                        if(now+f(i+k,j+k)<=v)
                            now+=f(i+k,j+k);
                        else
                            break;
                    }
                    sum[i][j]=now;
                    l[i][j]=k;
                    ans+=k;
                }
            }
    
            printf("%lld
    ",ans);
        }
        return 0;
    }
    View Code

    01:03(9A)

  • 相关阅读:
    java基础35 双例集合Map及其常用方法
    java基础34 泛型的使用
    java基础33 Set集合下的HashSet集合和TreeSet集合
    java基础32 List集合下的ArrayList集合
    部分日期时间函数
    SQL语句常见视图操作部分试题(一)
    高级子查询常见用法及举例
    DDL/DML/DCL区别概述
    SQL语句常见DDL/DML/DCL操作部分试题(一)
    Create database 创建数据库
  • 原文地址:https://www.cnblogs.com/xutianshu/p/10591561.html
Copyright © 2011-2022 走看看