• 23号~26号的3场cf


    23号~26号的10场cf

     第一场:#272 div1

    A题:

    推下公式然后统计,注意a/b=c,a=c*b+(a%b),比如7/3=2,7=2*3+7%3。

    没什么好讲的,A题就是个水题。

    #include<bits/stdc++.h>
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define rep(i,a,b) for(int i=a;i>=b;i--)
    
    using namespace std;
    
    const int maxn=1000100;
    const int INF=(1<<29);
    typedef long long ll;
    const ll MOD=1000000007;
    
    ll a,b;
    
    int main()
    {
        cin>>a>>b;
        ll ans=0;
        for(int k=1;k<=a;k++){
            ll tmp=(((k*b+1)%MOD)*(((b-1)*b/2)%MOD))%MOD;
            ans=(ans%MOD+tmp%MOD)%MOD;
        }
        cout<<ans<<endl;
        return 0;
    }
    View Code

    B题:

    找规律。。但是前提得知道,gcd(a,b)=c ----》 gcd(a/c,b/c)=1。

    四个数的gcd为k可以让这些数除以k,这样变成k=1的情况,问题转化成找四个互质的数。K>1的时候让结果乘以K就行了。

    然后就是找规律了。。。首先不能出现两个偶数,然后发现偶数出现在第二个比较好。。

    1 2 3 5

    7 8 9 11

    13 14 15 17

    19 20 21 23

    .......

    然后规律就很明显了。。

    (6*i-5),(6*i-4),(6*i-3),(6*i-1)

    首先还是要想到转换为互质简化问题,接着从前几项开始找规律,稍稍观察就能找到了。

    #include<bits/stdc++.h>
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define rep(i,a,b) for(int i=a;i>=b;i--)
    
    using namespace std;
    
    const int maxn=1000100;
    const int INF=(1<<29);
    
    int n,k;
    
    int main()
    {
        while(cin>>n>>k){
            cout<<(6*n-1)*k<<endl;
            for(int i=1;i<=n;i++){
                printf("%d %d %d %d
    ",(6*i-5)*k,(6*i-4)*k,(6*i-3)*k,(6*i-1)*k);
            }
        }
        return 0;
    }
    View Code

    C题是dp题,也涉及到字符串,必须补啊。。明天早上起来再补,补完C题后直接开第二场。

     C题:

    感觉和上次dp专题赛的数字那题有些类似,都是前i个找j个的形式,然后进行转移,前一状态是i-1,但不一定j-1,可以是j-k。

    当然dp的前提还是范围比较小。

    这个可以单独写个题解:http://www.cnblogs.com/--560/p/4754253.html

    第一场,爆零了。

     第二场:#274 div1

    A题:水题,贪心,排个序就行了。

    #include<bits/stdc++.h>
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define MS0(a) memset(a,0,sizeof(a))
    
    using namespace std;
    
    typedef long long ll;
    const int INF=(1<<29);
    const int maxn=1000100;
    
    struct Node
    {
        ll a,b;
        friend bool operator<(Node A,Node B)
        {
            if(A.a<B.a) return 1;
            if(A.a==B.a) return A.b<B.b;
            return 0;
        }
    };
    int n;
    Node p[maxn];
    
    int main()
    {
        freopen("in.txt","r",stdin);
        while(cin>>n){
            for(int i=1;i<=n;i++){
                scanf("%I64d%I64d",&p[i].a,&p[i].b);
            }
            sort(p+1,p+n+1);
            ll tmp=1;
            for(int i=1;i<=n;i++){
                if(p[i].b>=tmp) tmp=p[i].b;
                else tmp=p[i].a;
            }
            cout<<tmp<<endl;
        }
        return 0;
    }
    View Code

    B题:水题。用几个map或set随便弄一下就行了。

    #include<bits/stdc++.h>
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define MS0(a) memset(a,0,sizeof(a))
    
    using namespace std;
    
    typedef long long ll;
    const int INF=(1<<29);
    const int maxn=1000100;
    
    ll n,l,x,y;
    ll a[maxn];
    map<ll,int> X,Y,A;
    
    int main()
    {
        freopen("in.txt","r",stdin);
        while(cin>>n>>l>>x>>y){
            X.clear(),Y.clear(),A.clear();
            for(int i=1;i<=n;i++) scanf("%I64d",&a[i]),A[a[i]]++;
            bool flagX=0,flagY=0;
            set<ll> sX,sY;
            for(int i=1;i<=n;i++){
                if(A[a[i]+x]||A[a[i]-x]) flagX=1;
                if(A[a[i]+y]||A[a[i]-y]) flagY=1;
            }
            if(flagX&&flagY) puts("0");
            else{
                for(int i=1;i<=n;i++){
                    if(a[i]+x<=l) sX.insert(a[i]+x);
                    if(a[i]-x>=0) sX.insert(a[i]-x);
                    if(a[i]+y<=l) sY.insert(a[i]+y);
                    if(a[i]-y>=0) sY.insert(a[i]-y);
                }
                if(flagY){
                    cout<<1<<endl;
                    cout<<*(sX.begin())<<endl;
                }
                else if(flagX){
                    cout<<1<<endl;
                    cout<<*(sY.begin())<<endl;
                }
                else{
                    bool tag=0;
                    int ans;
                    for(set<ll>::iterator it=sX.begin();it!=sX.end();it++){
                        if(sY.find(*it)!=sY.end()){
                            tag=1;ans=*it;
                            break;
                        }
                    }
                    if(tag){
                        cout<<1<<endl;
                        cout<<ans<<endl;
                    }
                    else{
                        cout<<2<<endl;
                        cout<<*(sX.begin())<<" "<<*(sY.begin())<<endl;
                    }
                }
            }
        }
        return 0;
    }
    View Code

    C题:

    比赛的最后时刻想到了dp,不过没有写下去,其实就是dp!

    关键还是找转态转移。

    dp+前缀和优化。

    这个可以单独写个题解:

    #include<bits/stdc++.h>
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define MS0(a) memset(a,0,sizeof(a))
    
    using namespace std;
    
    typedef long long ll;
    const int INF=(1<<29);
    const int maxn=5010;
    
    const ll p=1000000007;
    ll n,a,b,k;
    ll dp[maxn][maxn];
    ll sum[maxn];
    
    int main()
    {
        freopen("in.txt","r",stdin);
        while(cin>>n>>a>>b>>k){
            MS0(dp);
            for(int i=1;i<=n;i++) dp[1][i]=(abs(a-i)<abs(a-b))&&(i!=a);
            sum[0]=0;
            for(int i=1;i<=n;i++) sum[i]=(sum[i-1]+dp[1][i])%p;
            for(int i=2;i<=k;i++){
                for(int j=1;j<=n;j++){
                    if(j<b){
                        dp[i][j]=(dp[i][j]+(sum[(b+j-1)/2]-sum[0]-(sum[j]-sum[j-1])+3*p)%p)%p;
                    }
                    else if(j>b){
                        dp[i][j]=(dp[i][j]+(sum[n]-sum[(b+j)/2]-(sum[j]-sum[j-1])+3*p)%p)%p;
                    }
                }
                for(int j=1;j<=n;j++){
                    sum[j]=(sum[j-1]+dp[i][j]%p)%p;
                }
            }
            ll ans=0;
            for(int i=1;i<=n;i++){
                ans=(ans%p+dp[k][i]%p)%p;
            }
            cout<<ans<<endl;
        }
        return 0;
    }
    View Code

     这场轻松过了AB,要是打那次的div2,过CD上紫?

     下一场?能过dp?
     
     
    第三场:#275 div1
    A题:水题,20min过。
    #include<bits/stdc++.h>
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define MS0(a) memset(a,0,sizeof(a))
    
    using namespace std;
    
    typedef long long ll;
    const int maxn=1000100;
    const int INF=(1<<29);
    
    ll n,k;
    
    int main()
    {
        freopen("in.txt","r",stdin);
        while(cin>>n>>k){
            int a=1;
            for(int i=1;i<=n-k;i++){
                printf("%d ",a++);
            }
            int c=n,d=a;
            for(int i=1;i<=k;i++){
                if(i&1) printf("%d ",c--);
                else printf("%d ",d++);
            }
            puts("");
        }
        return 0;
    }
    View Code

    B题:线段树。居然没有看出是线段树。。主要是位运算的问题,位运算和一般的增减还是不一样的。

    #include<bits/stdc++.h>
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    
    using namespace std;
    
    const int maxn=1000100;
    
    typedef long long ll;
    int N,Q;
    ll val[maxn<<2];
    struct Query
    {
        int l,r;
        ll ask;
    };Query q[maxn];
    
    void push_up(int rt)
    {
        val[rt]=val[rt<<1]&val[rt<<1|1];
    }
    
    void push_down(int rt)
    {
        val[rt<<1]|=val[rt];
        val[rt<<1|1]|=val[rt];
    }
    
    void update(int L,int R,ll c,int l,int r,int rt)
    {
        if(L<=l&&r<=R){
            val[rt]|=c;
            return;
        }
        push_down(rt);
        int m=(l+r)>>1;
        if(L<=m) update(L,R,c,lson);
        if(R>m) update(L,R,c,rson);
        push_up(rt);
    }
    
    ll query(int L,int R,int l,int r,int rt)
    {
        if(L<=l&&r<=R) return val[rt];
        push_down(rt);
        int m=(l+r)>>1;
        ll res=(1LL<<60)-1;
        if(L<=m) res&=query(L,R,lson);
        if(R>m) res&=query(L,R,rson);
        push_up(rt);
        return res;
    }
    
    void get(int l,int r,int rt)
    {
        if(l==r){
            printf("%I64d ",val[rt]);
            return;
        }
        push_down(rt);
        int m=(l+r)>>1;
        get(lson);
        get(rson);
        push_up(rt);
    }
    
    int main()
    {
        //freopen("in.txt","r",stdin);
        while(cin>>N>>Q){
            memset(val,0,sizeof(val));
            for(int i=1;i<=Q;i++){
                scanf("%d%d%I64d",&q[i].l,&q[i].r,&q[i].ask);
                update(q[i].l,q[i].r,q[i].ask,1,N,1);
            }
            bool flag=1;
            for(int i=1;i<=Q;i++){
                if(query(q[i].l,q[i].r,1,N,1)!=q[i].ask){
                    flag=0;break;
                }
            }
            if(flag){
                puts("YES");
                get(1,N,1);
                puts("");
            }
            else puts("NO");
        }
        return 0;
    }
    View Code

    明天再补。

    C题:概率+dp,略涉及字符串。补补补!

    div2 B题:水题二分,画个集合的韦恩图容斥一下就好了。

    #include<bits/stdc++.h>
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define MS0(a) memset(a,0,sizeof(a))
    
    using namespace std;
    
    typedef long long ll;
    const int maxn=1000100;
    const int INF=(1<<29);
    
    ll c1,c2,x,y;
    
    bool check(ll n)
    {
        ll px=n/x;
        ll py=n/y;
        ll pxy=n/(x*y);
        return n-px>=c1&&n-py>=c2&&n-pxy>=c1+c2;
    }
    
    ll bin(ll l,ll r)
    {
        while(l<r){
            ll m=(l+r)>>1;
            if(check(m)) r=m;
            else l=m+1;
        }
        return r;
    }
    
    int main()
    {
        freopen("in.txt","r",stdin);
        while(cin>>c1>>c2>>x>>y){
            ll n=bin(1,1LL<<60);
            cout<<n<<endl;
        }
        return 0;
    }
    View Code

    虽然20分钟过了A,不过线段树居然没过,没过的原因还是位运算的细节没想清楚,觉得处理起来比较麻烦,就没往线段树方面想了,还是经验问题。C题比较难,过的人有点少,但既然是dp,又涉及字符串,还是得补,增加经验。

    不过要是做了那一场的div2,40min3题?可能也会紫?如果做出线段树呢?

    明天补完BC,有时间再开一场,没时间就准备下午的组队赛了。

    感觉该补线段树了

    ====================

    做了一些线段树离线的题,补了Orz_panda的A题(线段树离线)和I题(状压dp),回来刷cf了。

    第四场:

    A题:水题。求[l,r]中二进制表示出现的1的个数最多的数,如果多种答案,输出最小的。

    本来以为是数位dp,想了一下原来是个水题,比赛的时候用字符串模拟,51min才过,其实直接用数字二进制弄更简单些。

    #include<bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    
    const int maxn=120;
    
    int n;
    ll l,r;
    int numL[maxn],numR[maxn];
    int nL,nR;
    
    int main()
    {
       // freopen("in.txt","r",stdin);
        cin>>n;
        while(n--){
            scanf("%I64d%I64d",&l,&r);
            int tmp[maxn];
            ll tl=l,tr=r;
            nL=nR=0;
            while(tl){
                tmp[nL++]=tl%2;
                tl>>=1;
            }
            for(int i=0;i<nL;i++) numL[i]=tmp[nL-1-i];
            //cout<<tr<<endl;
            while(tr){
                tmp[nR++]=tr%2;
                tr>>=1;
            }
            for(int i=0;i<nR;i++) numR[i]=tmp[nR-i-1];
           // cout<<nL<<" "<<nR<<endl;
            bool flag=1;
            for(int i=0;i<nR;i++){
                if(!numR[i]){
                    flag=0;break;
                }
            }
            //cout<<flag<<endl;
            //for(int i=0;i<nR;i++) cout<<numR[i]<<" ";cout<<endl;
            if(flag){
                printf("%I64d
    ",r);
                continue;
            }
            //cout<<nL<<" "<<nR<<endl;
            if(nL<nR){
                //cout<<nL<<" "<<((1LL<<nL)-1)<<endl;
                printf("%I64d
    ",(1LL<<(nR-1))-1);
                continue;
            }
            int ans[maxn];
            memset(ans,0,sizeof(ans));
            bool tag=0;
            for(int i=0;i<nR;i++){
                if(tag){
                    ans[i]=1;continue;
                }
                if(numL[i]!=numR[i]){
                    tag=1;
                    bool tag2=0;
                    for(int j=i+1;j<nR;j++){
                        if(numR[j]==0){
                            tag2=1;break;
                        }
                    }
                    if(tag2) ans[i]=0;
                    else ans[i]=1;
                    continue;
                }
                ans[i]=numL[i];
            }
            ll Ans=0;
           // cout<<"f"<<endl;
            for(int i=0;i<nR;i++){
                if(ans[i]) Ans+=(1LL<<(nR-i-1));
            }
            printf("%I64d
    ",Ans);
        }
        return 0;
    }
    View Code

    B题:这题其实也不难。。

    给一个序列,找一对(ai,aj)使得ai>aj,且ai%aj最大。

    先排序,然后遍历a[j]*k,k=2,3,....,查找第一个比a[j]*k小的,取余数更新答案。

    复杂度 :  a[j]*k <= Max,因此这部分复杂度类似素数筛(n/1+n/2+n/3+...+n/1=logn),后面二分查找也是logn,总复杂度(n*logn*logn).

    #include<bits/stdc++.h>
    
    using namespace std;
    
    const int maxn=1000100;
    const int INF=(1<<29);
    
    int n;
    int a[maxn];
    
    int bin(int l,int r,int x,int mod)
    {
        while(l<=r){
            int m=(l+r)>>1;
           // cout<<l<<" "<<r<<" "<<m<<" "<<a[m]<<endl;
            if((m==n&&a[m]<x)||(a[m]<x&&a[m+1]>=x)) return a[m]%mod;
            if(a[m]>=x) r=m-1;
            else l=m+1;
        }
        return 0;
    }
    
    int main()
    {
        while(cin>>n){
            for(int i=1;i<=n;i++) scanf("%d",&a[i]);
            sort(a+1,a+n+1);
            n=unique(a+1,a+n+1)-(a+1);
            int Max=a[n];
            int ans=0;
            for(int i=1;i<=n;i++){
                for(int j=2;a[i]*(j-1)<=Max;j++){
                   // cout<<i+1<<" "<<n<<" "<<a[i]*j<<" "<<a[i]<<endl;
                    ans=max(bin(i+1,n,a[i]*j,a[i]),ans);
                }
            }
            cout<<ans<<endl;
        }
        return 0;
    }
    View Code

     第五场:(#273 div 2)

    A题:略。

    B题:略。

    C题:

    给定a个红球,b个白球,c个蓝球,求每次选择确定的三个装饰桌子,不能选完全相同的三个,最多能装饰多少桌子。

    不妨设a>=b>=c,当a<=(b+c)*2时,直接除以3。

    #include<bits/stdc++.h>
    
    using namespace std;
    
    const int maxn=1000100;
    const int INF=(1<<29);
    typedef long long ll;
    
    ll r,b,g;
    
    void solve()
    {
        ll a[3]={r,b,g};
        sort(a,a+3);
        r=a[2];b=a[1];g=a[0];
        if(r>(b+g)*2) r=(b+g)*2;
        cout<<(r+b+g)/3<<endl;
    }
    
    int main()
    {
        while(cin>>r>>b>>g){
            solve();
        }
        return 0;
    }
    View Code

    D题:

     dp题。http://codeforces.com/contest/478/problem/D

    #include<bits/stdc++.h>
    
    using namespace std;
    
    const int maxn=200100;
    const int INF=(1<<29);
    typedef long long ll;
    const ll MOD=1000000007;
    
    ll dp[2][maxn];
    int r,g;
    
    int main()
    {
        while(~scanf("%d%d",&r,&g)){
            memset(dp,0,sizeof(dp));
            dp[1][0]=r?1:0;
            dp[1][1]=g?1:0;
            ll H=0;
            for(int x=1;;x++){
                if((r+g)-x*(x+1)/2>=0) H=x;
                else break;
            }
            ll sum=1;
            for(int i=2;i<=H;i++){
                sum+=i;
                for(int j=0;j<=g&&j<=sum;j++){
                    dp[i%2][j]=0;
                    if(sum-j<=r){
                        dp[i%2][j]=(dp[i%2][j]+dp[(i+1)%2][j])%MOD;
                        if(j>=i) dp[i%2][j]=(dp[i%2][j]+dp[(i+1)%2][j-i])%MOD;
                    }
                }
            }
            ll ans=0;
            for(int i=0;i<=g;i++) ans=(ans+dp[H%2][i])%MOD;
            cout<<ans<<endl;
        }
        return 0;
    }
    View Code

    E题:数位dp,待补。。

    没有AC不了的题,只有不努力的ACMER!
  • 相关阅读:
    翻译一下libtiff的手册
    LIBTIFF读写黑白TIFF
    LIBTIFF存储代码,存图、拼图
    几点TIFF的说明
    TIFF Tag TileWidth
    TIFF Tag Orientation
    OpenCV 加速图像处理
    Qt QString 、String、char* 三者之间相互转换
    PackBits解压缩算法
    关于LZW算法的压缩与解压缩
  • 原文地址:https://www.cnblogs.com/--560/p/4753166.html
Copyright © 2020-2023  润新知