• [CSP-S模拟测试96]题解


    以后不能再借没改完题的理由不写题解了……

    A.求和

    求$sum sum i+j-1$

    柿子就不化了吧……这年头pj都不考这么弱智的公式化简了……

    坑点1:模数不定,可能没有2的逆元,那么只要先把乘数里的2去掉就好了。

    坑点2:1e18炸long long $ ightarrow$ 慢速乘即可

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<vector>
    using namespace std;
    typedef long long ll;
    ll x,y,xx,yy,mod;
    ll mul(ll a,ll b)
    {
        ll res=0;
        while(b)
        {
            if(b&1)res+=a,res%=mod;
            a=(a+a)%mod;
            b>>=1;
        }
        return res;
    }
    vector<ll> fac;
    #define F
    int main()
    {
    #ifdef F
        freopen("sum.in","r",stdin);
        freopen("sum.out","w",stdout);
    #endif
        /*mod=1e9+7;
        cout<<mul(100000,3)<<endl;*/
        scanf("%lld%lld%lld%lld%lld",&x,&y,&xx,&yy,&mod);
        int cnt=1;
        fac.push_back(x+xx);
        fac.push_back(xx-x+1);
        fac.push_back(yy-y+1);
        for(int i=0;i<3;i++)
            if(cnt&&fac[i]%2==0)fac[i]/=2,cnt--;
        ll ans=1;
        for(int i=0;i<3;i++)
            ans=mul(ans,fac[i]);
        fac.clear();cnt=1;
        fac.push_back(y+yy);
        fac.push_back(xx-x+1);
        fac.push_back(yy-y+1);
        for(int i=0;i<3;i++)
            if(cnt&&fac[i]%2==0)fac[i]/=2,cnt--;
        ll res=1;
        for(int i=0;i<3;i++)
    
    
            res=mul(res,fac[i]);
        (ans+=res)%=mod;
        ans-=mul(xx-x+1,yy-y+1)%mod;
        (ans+=mod)%=mod;
        printf("%lld
    ",ans);
        /*ans=(x+xx)*(xx-x+1)%mod*(yy-y+1)%mod*inv%mod;
        ans+=(xx-x+1)*(y+yy)%mod*(yy-y+1)%mod*inv%mod;ans%=mod;
        ans-=(xx-x+1)*(yy-y+1)%mod;ans=(ans+mod)%mod;
        printf("%lld
    ",ans);*/
        return 0;
    }
    

    B.分组配对

    显然,最大 $ imes$ 最大$+$ 第二大 $ imes$ 第二大 $+...$的方式能使小组总值最大。

    这里简单写一下证明,考虑只有两对的情况。

    设它们为$a,b,a-x,b-y$,因为实力值为正整数所以必有$a>x,b>y$

    那么按排名配对的总值为$ab imes 2 -ay-bx+xy$

    交叉配对的为$ab imes 2 -ay-bx$

    很显然前者大于后者。

    所以只要贪心地往右扫,到不能加入组里时开新组就好了。

    暴力的话每次都sort或二分查找肯定是不行的

    由于往右扩展这个过程具有单调性,可以考虑二分

    但check一次的代价也很大,需要设法减小二分范围

    那么可以先倍增到一个不合法的位置,再以$1<<(p-1)$为左边界,$1<<p$为右边界进行二分

    时间复杂度最劣为$O(n log^2 n)$。

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<vector>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    ll read()
    {
        ll x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    const int N=5e5+5;
    int n;
    ll m;
    ll a[N],b[N];
    vector<ll> nowa,nowb;
    bool check(int l,int r)
    {
        vector<ll> tmpa,tmpb;
        swap(nowa,tmpa);swap(nowb,tmpb);
        for(int i=l;i<=r;i++)
            nowa.push_back(a[i]),nowb.push_back(b[i]);
        sort(nowa.begin(),nowa.end());sort(nowb.begin(),nowb.end());
        int sz=nowa.size();ll res=0;
        for(int i=sz-1;i>=0;i--)
        {
            res+=nowa[i]*nowb[i];
            if(res>m)return 0;
        }
        return 1;
    }
    int find(int x)
    {
        int p=0;
        for(int i=0; ;i++)
        {
            p=i;
            if(!check(x,min(x+(1<<i)-1,n)))break;      
            if(x+(1<<i)-1>=n)break;
        }
        int l=x+(1<<p-1)-1,r=min(x+(1<<p)-1,n),res=l;
        while(l<=r)
        {
            int mid=l+r>>1;
            if(check(x,mid))res=mid,l=mid+1;
            else r=mid-1;
        }
        return res;
    }
    #define F
    int main()
    {
    #ifdef F
        freopen("pair.in","r",stdin);
        freopen("pair.out","w",stdout);
    #endif
        n=read();m=read();
        for(int i=1;i<=n;i++)
            a[i]=read();
        for(int i=1;i<=n;i++)
            b[i]=read();
        int ans=0;
        int i=1;
        while(i<=n)i=find(i)+1,ans++;
        printf("%d
    ",ans);
        return 0;
    }
    /*
    3 50
    6 7 6
    6 3 5
    */
    

    C.城市游戏

  • 相关阅读:
    c语言--第零次作业
    Beta 冲刺(3/7)
    Beta 冲刺(2/7)
    福大软工 · 第十次作业
    Beta 冲刺(1/7)
    BETA 版冲刺前准备(团队)
    Alpha 事后诸葛亮(团队)
    Alpha冲刺(10/10)
    Alpha 冲刺 (9/10)
    Alpha 冲刺 (8/10)
  • 原文地址:https://www.cnblogs.com/Rorschach-XR/p/11779769.html
Copyright © 2020-2023  润新知