蓝桥杯 历届试题 1119

来源:互联网 发布:c语言atm机程序 编辑:程序博客网 时间:2024/06/05 03:00

分糖果

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

#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;}
0 0