zoukankan      html  css  js  c++  java
  • Codeforces Round #448 (Div. 2)

    A. Pizza Separation

    枚举连续的即可。

    #include <bits/stdc++.h>
    using namespace std;
    using ll=long long;
    int n,x;
    int a[780];
    
    int main(){
        //freopen("in.txt","r",stdin);
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",a+i),a[i+n]=a[i];
        for(int i=1;i<=n+n;i++)
            a[i]=a[i-1]+a[i];
        int mn=360;
        for(int i=1;i<=n;i++)
            for(int j=i;j<=i+n-1;j++)
                mn=min(mn,abs(abs(a[j]-a[i-1])*2-360));
        cout<<mn;
        return 0;
    }
    

    B. XK Segments

    对于$a_i$,大于等于他的x的倍数的第k个可以迅速求出来。
    那么就变成求这一段区间的数字的个数。二分即可。

    #include <bits/stdc++.h>
    using namespace std;
    using ll=long long;
    const int mod = 1e9+7;
    int n;
    ll x,k;
    ll a[100005];
    int main(){
        //freopen("in.txt","r",stdin);
        scanf("%d%lld%lld",&n,&x,&k);
        for(int i=1;i<=n;i++)
            scanf("%lld",&a[i]);
        sort(a+1,a+1+n);
        ll res=0;
        for(int i=1;i<=n;i++){
            ll l=max(a[i],((a[i]-1)/x+k)*x),r=((a[i]-1)/x+k+1)*x;
            ll tmp=upper_bound(a+1,a+1+n,r-1)-lower_bound(a+1,a+1+n,l);
            res+=max(0ll,tmp);
        }
        cout<<res;
        return 0;
    }
    

    C. Square Subsets

    将所有数字分解因子之后会变成 $a_i = 2{p_1}+3{p_2}+...+7^{p_4}+...$。
    最大质因子大于7的数字只会有一个质因子,此列只会有一个非0系数。
    那么原题就会变成满足: $x_1p_1+x_2p_2+...+x_np_n equiv 0 (mod 2)$的方程组。
    求其解的个数,等于求矩阵的秩。
    求出秩为$k$,答案是$2^{n-k}-1$。
    Q老师的写法。

    #include <bits/stdc++.h>
    using namespace std;
    using ll=long long;
    const int mod = 1e9+7;
    int n,x;
    int p[100],top=0;
    vector<int> v;
    bool isprime(int n){
        for(int i=2;i*i<=n;i++)
            if(n%i==0) return 0;
        return 1;
    }
    int main(){
        //freopen("in.txt","r",stdin);
        for(int i=2;i<=70;i++)
            if(isprime(i)) p[top++]=i;
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&x);
            int t=0;
            for(int j=0;j<top;j++){
                if(x%p[j]) continue;
                while(x%p[j]==0){
                    t^=(1<<j);
                    x/=p[j];
                }
            }
            for(auto ex:v)
                t=min(t,t^ex);
            if(t) v.push_back(t);
        }
        int res=1;
        //cout<<v.size()<<endl;
        for(int i=(int)v.size();i<n;i++)
            res=(res+res)%mod;
        res=(res-1+mod)%mod;
        cout<<res;
        return 0;
    }
    

    D. String Mark

    转换为求比$S_2$小的和比$S_1$小的答案之差再减去1。
    对于当前点,计算两种状态。
    1.已经可以决定拼出长度比对比串小,即ch<s[i]。后面应该是$frac{len!}{l_1!l_2!...l_k!}$,边除边做就能$O(1)$。
    2.当前状态保持相等。

    #include <bits/stdc++.h>
    
    using namespace std;
    using ll=long long;
    const int mod = 1e9+7;
    const int maxn = 1e6+5;
    char s1[maxn],s2[maxn];
    ll fac[maxn],inv[maxn];
    int len,n;
    int cnt[128];
    
    inline ll power(ll a,ll b){
        if(!b) return 1ll;
        ll ret=power(a,b>>1);
        ret=ret*ret%mod;
        if(b&1) return ret*a%mod;
        return ret;
    }
    
    void init(){
        #define N maxn-1
        fac[0]=1;
        for(ll i=1;i<=N;i++)
            fac[i]=fac[i-1]*i%mod;
        inv[N]=power(fac[N],mod-2);
        for(ll i=N;i>=1;i--)
            inv[i-1]=inv[i]*i%mod;
        //cout<<inv[0]<<endl;
    }
    
    ll calc(char s[],int n){
        memset(cnt,0,sizeof cnt);
        for(int i=0;i<n;i++)
            cnt[s1[i]]++;
        ll tmp=fac[n];
        for(int i='a';i<='z';i++)
            tmp=tmp*inv[cnt[i]]%mod;//all
        ll ret=0;
        for(int i=0;i<n;i++){
            tmp=tmp*power(n-i,mod-2)%mod;//n-i
            for(int x='a';x<s[i];x++)
                if(cnt[x])
                    ret=(ret+tmp*cnt[x]%mod)%mod;
            tmp=tmp*cnt[s[i]]%mod;
            cnt[s[i]]--;
            if(cnt[s[i]]<0) return ret;
        }
        return ret;
    }
    
    int main(){
        //freopen("in.txt","r",stdin);
        init();
        scanf("%s%s",s1,s2);
        n=strlen(s1);
        ll res=calc(s2,n)-calc(s1,n);
        res--;
        res=(res%mod+mod)%mod;
        cout<<res;
        return 0;
    }
    

    E. Eyes Closed

    查询时查询区间和。
    修改时,
    假设左边区间值为left长度为l1,右边值为right长度为l2。
    修改左边其实是左边每个值都有1/l1的几率换掉,那么就是有(l1-1)/l1的概率保存下来。
    保留下来的期望就是s*(l1-1)/l1再加上右边换过来的期望right/l2/l1。
    维护三个标记即可。

    #include <bits/stdc++.h>
    using namespace std;
    using ll=long long;
    using db=double;
    const int mod = 1e9+7;
    const int maxn = 1e5+5;
    int n,m,opt,l[2],r[2];
    int a[maxn];
    int len[maxn<<4];
    struct tree{
        db s,mul,add;
    }T[maxn<<4];
    
    void pup(int id){
        T[id].s=T[id<<1].s+T[id<<1|1].s;
    }
    void pdd(int id){
        T[id<<1].s=T[id<<1].s*T[id].mul+T[id].add*len[id<<1];
        T[id<<1|1].s=T[id<<1|1].s*T[id].mul+T[id].add*len[id<<1|1];
        T[id<<1].add=T[id<<1].add*T[id].mul+T[id].add;
        T[id<<1|1].add=T[id<<1|1].add*T[id].mul+T[id].add;
        T[id<<1].mul=T[id<<1].mul*T[id].mul;
        T[id<<1|1].mul=T[id<<1|1].mul*T[id].mul;
        T[id].add=0;
        T[id].mul=1;
    }
    
    void build(int l,int r,int id){
        T[id].mul=1;
        T[id].add=0;
        len[id]=r-l+1;
        if(l==r){
            T[id].s=a[l];
            return ;
        }
        int mid=(l+r)/2;
        build(l,mid,id<<1);
        build(mid+1,r,id<<1|1);
        pup(id);
    }
    
    void update(int L,int R,db d,db rat,int l,int r,int id){
        if(L<=l&&r<=R){
            T[id].s=T[id].s*rat+d*len[id];
            T[id].add=T[id].add*rat+d;
            T[id].mul=T[id].mul*rat;
            return;
        }
        pdd(id);
        int mid=(l+r)/2;
        if(mid>=L) update(L,R,d,rat,l,mid,id<<1);
        if(mid<R) update(L,R,d,rat,mid+1,r,id<<1|1);
        pup(id);
    }
    
    db query(int L,int R,int l,int r,int id){
        if(L<=l&&r<=R){
            return T[id].s;
        }
        pdd(id);
        int mid=(l+r)/2;
        if(mid>=R) return query(L,R,l,mid,id<<1);
        else if(mid<L) return query(L,R,mid+1,r,id<<1|1);
        else return query(L,R,l,mid,id<<1)+query(L,R,mid+1,r,id<<1|1);
    }
    
    int main(){
        //freopen("in.txt","r",stdin);
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%d",a+i);
        build(1,n,1);
        while(m--){
            scanf("%d",&opt);
            if(opt==1){
                scanf("%d%d%d%d",&l[0],&r[0],&l[1],&r[1]);
                db left=query(l[0],r[0],1,n,1);
                db right=query(l[1],r[1],1,n,1);
                update(l[0],r[0],right/(r[1]-l[1]+1)/(r[0]-l[0]+1),1.0*(r[0]-l[0])/(r[0]-l[0]+1),1,n,1);
                update(l[1],r[1],left/(r[0]-l[0]+1)/(r[1]-l[1]+1),1.0*(r[1]-l[1])/(r[1]-l[1]+1),1,n,1);
            } else {
                scanf("%d%d",&l[0],&r[0]);
                db res=query(l[0],r[0],1,n,1);
                printf("%.12lf
    ",res);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    ajax chrome load
    不一样的自拍
    jQuery点击空白关闭弹出层
    笔记整理
    带三角缺口的边框
    连续input在同一行对齐问题
    用Windows PowerShell 控制管理 Microsoft Office 365
    Qt and C++ Reflection,利用Qt简化C++的反射实现
    滴滴打车推出的“专车服务”后的见闻以及思考
    Exchange的AutoDiscover服务
  • 原文地址:https://www.cnblogs.com/foreignbill/p/7906837.html
Copyright © 2011-2022 走看看