• Codeforces Round #636 (Div. 3)


          解析:把式子的x分出来,就是x*(2^0+2^1......+2^k-1)=n。所以先累加括号里的值打个表,只要n能整除它就输出

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    const int maxn=1e5+20;
    ll a[maxn];
    int main()
    {
        ll n;
        int t;
        cin>>t;
        a[1]=1;
        ll sum = 1;
        for(int i=2;i<=1e9;i++)
        {
            sum*=2;
            a[i]=a[i-1]+sum;
            if(a[i]>=1e9)
                break;
        }
        while(t--)
        {
            cin>>n;
            for(int i=2;;i++)
            {
                if(n%a[i]==0)
                {
                    cout<<n/a[i]<<endl;break;
                }
            }
        }
    }

         题意:给出数组偶数长度n,能否输出一个:左边一半为偶数,右边一半为奇数,两边和相等。而且不存在重复数字。

         解析:n/2的结果如果不是偶数,那么就肯定构造不出。比如6/2=3,奇数个奇数相加是奇数,是没办法等于偶数部分的和的。偶数部分直接按2,6,10构造,之间的差距不能为2,奇数部分直接参考左边对应位置,每次+1,-1即可,偶数差>2保证了奇数不会出现相等。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    const int maxn=2e5+20;
    ll a[maxn];
    ll b[maxn];
    int main()
    {
        int t;
        cin>>t;
        while(t--)
        {
            int n;
            cin>>n;
            int md=n/2;
            if(md%2!=0)
                cout<<"NO"<<endl;
            else
            {
                cout<<"YES"<<endl;
                ll k=2,tot=0;
                ll sum=0;
                for(int i=1;i<=md;i++)
                {
                    sum+=k;
                    b[i]=k;        
                    k+=4;
                }
                int ok=0;
                for(int i=md+1;i<=n;i++)
                {
                    if(!ok)
                    {
                        b[i]=b[i-md]-1;
                        ok=1;
                    }
                    else
                    {
                        b[i]=b[i-md]+1;
                        ok=0;
                    }
                }
                for(int i=1;i<n;i++)
                    cout<<b[i]<<" ";
                    cout<<b[n]<<endl;
            }
        }
    }

         题意:给出一组数,找出最长的正负交替的子序列(这里是通过删除某些数而得到的子序列),输出它们的最大和。

         解析:找每一段连续正或负的最大值,累加即可。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<map>
    #include<set>
    using namespace std;
    typedef long long ll;
    const int maxn=2e5+10;
    const ll inf=0x3f3f3f3f3f;
    ll a[maxn];
    int main()
    {
        int t;
        cin>>t;
        while(t--)
        {
            int n;
            cin>>n;
            ll maxx=0;
            ll sum=0;
            for(int i=0;i<n;i++)
            {
                cin>>a[i];
                if(a[i]>0)
                {
                    maxx=max(maxx,a[i]);
                }
                else
                {
                    sum+=maxx;
                    maxx=0;
                }
            }
            ll maxx2=-inf;
            for(int i=0;i<n;i++)
            {
                if(a[i]<0)
                {
                    maxx2=max(maxx2,a[i]);
                }
                else
                {
                    if(maxx2!=-inf)
                        {
                            sum+=maxx2;
                        }            
                    maxx2=-inf;
                }
            }
            if(a[n-1]>0)  //少加的情况。
                sum+=maxx;
            else
                sum+=maxx2;
            cout<<sum<<endl;
        }
        return 0;
    }

         题意:给出偶数n个大小在[1,k]之间的数,操作是把任意一个数变成[1,k]之间的任意值。要达到每个ai+an-i+1都为定值x,求最少操作数。

         解析:我刚开始想的是,记录x出现的最大次数maxx,输出n-maxx,调了半天。原来我忽略了,ai和an-i+1,并不是随便改一个值就能使和达到[2,k]的任意值的。所以去分析每个x所对应的修改次数,下面开始讨论:

            sum=a[i]+a[n-i+1],maxx=max(a[i],a[n-i+1]),minn=min(a[i],a[n-i+1])

            1.如果x范围位于[2,minn],就算把maxx改成1,它们的和也是大于这个范围的,所以需要改动两次。

            2.如果x范围位于[minn+1,maxx+k],关于这个区间我解释一下:minn+1是把maxx变成1所得的和,maxx+k是把minn变成k所得的和,这是只改一个数所对应的和的范围。

           3.除了上面两种,就剩下[maxx+k+1,2*k]了。它和第一种一样,就算把minn变成k,它们的和也是小于这个范围的,所以要修改两个值。

          以上就需要差分数组维护了,关于差分数组,我有一篇博客可以参考:https://www.cnblogs.com/liyexin/p/11014218.html。对[L,R]每个数+1,就需要差分数组d[L]++,d[R+1]--。

          较为啰嗦的更新代码:

            for(int i=1;i<=n/2;i++)
            {
                ll sum=a[i]+a[n-i+1];
                ll minn=min(a[i],a[n-i+1]);
                ll maxx=max(a[i],a[n-i+1]);
                d[2]+=2;
                d[minn+1]-=2;
                d[minn+1]++;
                d[maxx+k+1]--;
                d[maxx+k+1]+=2;
                d[2*k+1]-=2;
                d[sum]--;
                d[sum+1]++;    //本来和就等于sum,所以不需要更新,需要--。
            }

          完整代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<map>
    #include<queue>
    typedef long long ll;
    using namespace std;
    const int maxn=2e5+10;
    ll a[maxn],d[2*maxn];  //差分数组开两倍
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            int n , k;
            scanf("%d%d",&n,&k);
            memset(d,0,sizeof(d));
            for(int i=1;i<=n;i++)
                scanf("%lld",&a[i]);
            for(int i=1;i<=n/2;i++)
            {
                ll sum=a[i]+a[n-i+1];
                ll minn=min(a[i],a[n-i+1]);
                ll maxx=max(a[i],a[n-i+1]);
                d[2]+=2;
                d[minn+1]-=2;
                d[minn+1]++;
                d[maxx+k+1]--;
                d[maxx+k+1]+=2;
                d[2*k+1]-=2;
                d[sum]--;
                d[sum+1]++;
            }
            ll minn=d[2];
            for(int i=3;i<=2*k;i++)    //x范围就是[2,2*k]看看哪一个x所需要的更新次数最少?
            {
                d[i]+=d[i-1];
                minn=min(d[i],minn);
            }
            cout<<minn<<endl;
        }
    }
  • 相关阅读:
    20145224&20145238 《信息安全系统设计基础》 第四次实验
    20145224&20145238 《信息安全系统设计基础》 第三次实验
    《信息安全系统设计基础》 第十一周学习总结
    20145211《信息安全系统设计基础》实验二 固件设计
    20145211《信息安全系统设计基础》实验五 网络通信
    20145211《信息安全系统设计基础》课程总结
    20145211 《信息安全系统设计基础》第十四周学习总结
    20145211 《信息安全系统设计基础》第十三周学习总结
    20145211《信息安全系统设计基础》第十二周学习总结
    GDB调试汇编堆栈过程分析
  • 原文地址:https://www.cnblogs.com/liyexin/p/12763687.html
Copyright © 2020-2023  润新知