后天就是蓝桥杯省赛了,今天总结一下这段时间做的蓝桥杯历届试题,还是一个一个题目的来吧!!!!!!

1,历届试题 矩阵翻硬币 

  这个题目说真的,我不会,在网上看了某神牛的题解答案为 ans=sqrt(n)*sqrt(m),具体怎么证明的我也不知道

2,历届试题 兰顿蚂蚁 

  这个题目怎么说呢,应该是送分题,直接模拟就可以了,这里就不说了。
 
3, 历届试题 分糖果
  这个题目好像之前在哪里做过,也是一道模拟题,弄两个数组搞一下就可以了
  下面是代码
#include<bits/stdc++.h>
using namespace std;
#define maxn 100+10

int a[2][maxn],n;
bool ok(int cur)
{
    for (int i=2;i<=n;i++) if (a[cur][i]!=a[cur][i-1]) return 0;
    return 1;
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        int cur=0,ans=0;
        for (int i=1;i<=n;i++) scanf("%d",&a[cur][i]);
        while(!ok(cur))
        {
            for (int i=1;i<=n;i++) {
                if (a[cur][i]%2) {
                    a[cur][i]++; ans++;
                }
            }
            for (int i=1;i<n;i++) a[1-cur][i]=a[cur][i+1]/2; a[1-cur][n]=a[cur][1]/2;
            for (int i=1;i<=n;i++) a[1-cur][i]+=(a[cur][i]/2);
            cur=1-cur;
        }
        printf("%d\n",ans);
    }
    return 0;
}
View Code

4,历届试题 小朋友排队 

  这个题让我想起了去年武大校赛的一道题,我永远忘不了,求最小交换次数就是求逆序对数,而这个题要算出每个小朋友交换的次数,故我们从前面求一次,再从后面求一次就可以了,我这里用树状数组来求

#include<bits/stdc++.h>
using namespace std;
#define maxn 1000000+10
#define LL long long
int a[maxn],n,b[maxn],num[maxn],c[maxn];
LL sum[maxn];
void init()
{
    sum[0]=0;
    for (LL i=1;i<maxn;i++) sum[i]=sum[i-1]+i;
}
int lowbit(int x){
    return x&(-x);
}
void add(int x)
{
    while(x<maxn)
    {
        a[x]++;
        x+=lowbit(x);
    }
}
int get_sum(int x)
{
    int ans=0;
    while(x>0) 
    {
        ans+=a[x];
        x-=lowbit(x);
    }
    return ans;
}
int main()
{
    init();
    while(scanf("%d",&n)!=EOF)
    {
        memset(a,0,sizeof(a));
        memset(num,0,sizeof(num));
        for (int i=1;i<=n;i++) scanf("%d",&b[i]),c[i]=b[i];
        sort(c+1,c+n+1);
        int m=unique(c+1,c+n+1)-c;
        for (int i=1;i<=n;i++) b[i]=lower_bound(c+1,c+m+1,b[i])-c;
        for (int i=1;i<=n;i++)
        {
            num[i]+=get_sum(maxn-1)-get_sum(b[i]);
            add(b[i]);
        }
        memset(a,0,sizeof(a));
        for (int i=n;i>=1;i--)
        {
            num[i]+=get_sum(b[i]-1);
            add(b[i]);
        }
        LL ans=0;
        //for (int i=1;i<=n;i++) printf("%d ",num[i]); printf("\n");
        for (int i=1;i<=n;i++) ans+=sum[num[i]];
        printf("%I64d\n",ans);
    }
    return 0;
}
View Code

5,历届试题 波动数列  

  这个题目一看,就知道是枚举a出现的次数和b出现的次数,网上有人用BFS和DFS来做,想都不想,肯定超时!!!!!!可以设第一个数为x,则

  S=n*x+sgm i*(a or -b),则知道a和b的数目为n*(n-1)/2,则可以枚举a的数目A,知道A后,就看组成A有多少种方法,而我们只能用1,2,。。。。n-1来组成A,这不就是01背包吗?这样题目就不能了,最坏情况下时间复杂度为O(n*n^2)=n^3,但是可以的70分了,正确的解法不知道

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define maxn 2000+100
const int mod=100000007;
LL dp[2000000];
int a[maxn];
void init(int n)
{
    for (int i=1;i<=n;i++) a[i]=i;
    int N=(n+1)*(n+2)/2;
    memset(dp,0,sizeof(dp));
    dp[0]=1;
    for (int i=1;i<=n;i++)
    {
        for (int j=N-a[i];j>=0;j--) 
        {
            if (dp[j])
            dp[j+a[i]]=(dp[j+a[i]]+dp[j])%mod;
        }
    }
}
int main()
{
    LL n,s,a,b;
    while(scanf("%I64d %I64d %I64d %I64d",&n,&s,&a,&b)!=EOF)
    {
        init(n-1);
        LL ans=0;
        LL N=n*(n-1)/2;
        for (LL i=0;i<=N;i++)
        {
            LL j=N-i;
            LL t=s-i*a+j*b;
            if (t%n==0) ans=(ans+dp[i])%mod;
        }
        printf("%I64d\n",ans);
    }
    return 0;
}
View Code

相关文章:

  • 2021-06-09
  • 2022-12-23
  • 2022-12-23
  • 2020-05-23
  • 2022-01-15
  • 2022-12-23
  • 2021-08-31
  • 2021-08-18
猜你喜欢
  • 2022-12-23
  • 2022-02-06
  • 2022-12-23
  • 2021-05-09
  • 2021-08-06
  • 2021-10-19
  • 2021-12-08
相关资源
相似解决方案