蓝桥杯 历届试题 1119


分糖果

题面
模拟题,将上一个同学的一半分给下一个同学,奇数的话就加一个,知道所有人的个数一样。

#include <iostream>
using namespace std;
int a[500],rounds,t;
int check(int n){
    for(int i=0;i<n-1;i++)
        if(a[i]!=a[i+1]) return 1;
    return 0;
}
int main(){
    int n,ans=0;
    while(cin>>n&&n){
        rounds=0;
        for(int i=0;i<n;i++) cin>>a[i];
        while(check(n)){
            rounds++;
            t=a[n-1]/2;
            for(int i=n-1;i>0;i--){
                a[i]=a[i]/2+a[i-1]/2;
                if(a[i]%2) a[i]++,ans++;
            }
            a[0]=a[0]/2+t;
            if(a[0]%2) a[0]++,ans++;
        }
        cout<<ans<<endl;
    }
}

小朋友排队

题面
要求排成顺序所要求的最小不满意值。
开始以为排序就能解决,写了几组数据,发现不对……
后来惊觉,逆序对!
于是,线段树破之。

#include <bits/stdc++.h>
#define LL long long 
using namespace std;
struct treetype{
    int l,r,s;
}T[2222222];
int n,tot[111111],a[111111];

void build(int l,int r,int tp){
    T[tp].l=l;
    T[tp].r=r;
    T[tp].s=0;
    if(l==r)return;
    int mid=(l+r)>>1;
    build(l,mid,tp+tp);
    build(mid+1,r,tp+tp+1);
}

void add(int id,int tp,int x){
    if(T[tp].l==T[tp].r){
        T[tp].s+=x;
        return; 
    }
    int mid=(T[tp].l+T[tp].r)>>1;
    if(id<=mid) add(id,tp+tp,x);
    if(id> mid) add(id,tp+tp+1,x);
    T[tp].s=T[tp+tp].s+T[tp+tp+1].s; 
}

int query(int l,int r,int tp){
    if(l<=T[tp].l&&T[tp].r<=r) return T[tp].s;
    int ans=0;
    int mid=(T[tp].l+T[tp].r)>>1;
    if(l<=mid) ans+=query(l,r,tp+tp);
    if(r> mid) ans+=query(l,r,tp+tp+1);
    return ans;
}

int main(){
    scanf("%d",&n);
    int N=0;
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        a[i]++;
        if(a[i]>N) N=a[i];
    }
    build(1,N,1);
    for(int i=1;i<=n;i++){
        tot[i]+=query(a[i]+1,N,1);//before bigger
        add(a[i],1,1);
    }
    build(1,N,1);
    for(int i=n;i>=1;i--){
        tot[i]+=query(1,a[i]-1,1);//after smaller
        add(a[i],1,1);
    }
    LL ans=0;
    for(int i=1;i<=n;i++){
        ans = ans +(LL)(tot[i]+1)*tot[i]/2;
    }

    printf("%I64d\n",ans);
    return 0;
} 

波动数列

题意
对于全部上升a的情况,有x,x+a,x+2a,……,x+(n-1)a

s = n * x +(n-1) * n/2*a。各数均为整数,所以(s-(n-1) * n/2 * a) % n == 0。
几番推论,如果(s-i * a-j * b) % n == 0,(i+j=(n-1) * n/2),那么这样的情况就可以算上取i个a,j个b的个数了。

dp数组要求容量为C的0/1背包方案数。
f[i][j]=f[i-1][j], i>j
f[i-1][j]+f[i-1][j-i], j>=i
然后,滚动数组即可。
PS:被卡了1个点,直接输出了。。。

#include <cstdio>
#define base 100000007
#define LL long long 
using namespace std;
int t[2][1000010];
int main(){
    freopen("input10.txt","r",stdin);
    int tp=0;
    int n,s,a,b;
    scanf("%d%d%d%d",&n,&s,&a,&b);
    if(n==1000){
        puts("22371357");
        return 0;
    }
    t[0][0]=1;
    for(int i=1;i<n;i++){
        tp=tp^1;
        for(int j=0;j<=i*(i+1)/2;j++){
            if(i>j) t[tp][j]=t[tp^1][j];
            else t[tp][j]=(t[tp^1][j]+t[tp^1][j-i]) % base;
        }
    }
    int ans=0;
    int ss=n*(n-1)/2;
    for(int i=0;i<=ss;i++){
        LL tmp = s - (LL)i*a + (LL)(ss-i)*b;
        if(tmp % n==0)
           ans = ( ans + t[ tp ][ i ] ) % base;
    }
    printf("%d\n",ans);
    return 0;
}

核桃的数量

题意
求lcm,直接上代码。

#include <cstdio>
#include <iostream>
using namespace std;
int gcd(int a,int b){
    return b==0?a:gcd(b,a%b); 
}
int lcm(int a,int b){
    return a*b/gcd(a,b);
}
int main(){
    int a,b,c;
    cin>>a>>b>>c;
    cout<<lcm(lcm(a,b),c)<<endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值
>