AcWing
  • 首页
  • 课程
  • 题库
  • 更多
    • 竞赛
    • 题解
    • 分享
    • 问答
    • 应用
    • 校园
  • 关闭
    历史记录
    清除记录
    猜你想搜
    AcWing热点
  • App
  • 登录/注册

NOIp题目选讲

作者: 作者的头像   robot_1 ,  2019-09-05 01:44:55 ,  所有人可见 ,  阅读 980


3


1

1.积木大赛
noip 2018 2013 d1t1
难度不是很大 画个图就好了
首先 你叠积木肯定会叠成金字塔形状的 对8?qaq
由图可知 我们可以发现一个事实
我们覆盖最长的则是最优(这好像是废话)
并且 一个相对于之前那个点是上升的
我们就要付出多少代价
这个点是下降的 我们不会付出代价的!!!
从左端点进行统计就好了 !

#include<iostream>

using namespace std;
int now,ans,n,a;
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a;
        if(a>now)  ans+=a-now;
        now=a;
    }
    cout<<ans;
    return 0;
}

2.小凯的疑惑
数学好的同学可以用裴蜀定理
而像我这种蒟蒻可以打暴力或者直接找规律qaq

//baoli
#include<iostream>

using namespace std;
int flag[1000010];
int main()
{
    int a,b,x,y;
    cin>>a>>b;
    for(x=0;x<=1000;x++)
      for(y=0;y<=1000;y++)
        flag[a*x+b*y]=1;
        for(int i=1000;i>=0;i--)
          if(flag==0)  cout<<i;

    return 0;
}
//gcd(a,b)=1;
/*
3 7
1,2,4,5,8,11,
3*4=12
3+7+3=13
7*2
*/
#include<iostream>

using namespace std;
int main()
{
    long long  a,b;
    cin>>a>>b;
    cout<<a*b-a-b;
    return 0;
}
/*  我在这里找的规律
3 4 5  6  (3-1)*(4-1)
3 5 7  8  (3-1)*(5-1)
3 7 11  12  (3-1)*(7-1)

(a-1)(b-1)==ab-a-b
*/

----------第三题麦森数
一、求位数

首先我们知道 与 有着相同的位数,因为2的次方满足了最后一位不为零的要求,所以减一后位数并不会改变,那么我们可以直接求 的位数。那么怎么求位数呢?我们不妨设 ,根据 的位数为 ,我们只要想办法把 中的底数2改为10,指数加一就是位数了。由此想到用10的几次方来代替2,那么就不难想到 ,这样便可以把 中的2代换掉,变为 。根据乘方的原理,将p乘进去,原式便可化为我们最终想要的形式 了,所以位数就是 。(提醒一下,C++中cmath库自带log10()函数…)//某人的博客
或者可以这想

N = 10 -> 位数为2;
N = 100 -> 位数为3;
N = 1000 -> 位数为4;
N = 12345 -> 位数为5;
可见自然数N的位数等于lg(N) + 1
所以,2的p次方减1的位数为:lg(2^p-1) + 1。有同学到这里就懵了,不会解,赶紧百度-_-。
我看到网站上很多就是直接求 lg(2^p)+1,而题目是求2^p-1的位数,为什么这里是2^p。跳的太快了,我脑壳疼。
其实,求2^p-1的位数和2^p的位数相同。(如果2^p-1和2^p的位数不同的话,只有2^p是10的倍数:
10,100, 1000…。如10减1等于9,9只有1位数,而10有两位数。可知2的N次方是:2,4,8,16,3,264…,尾数是2,4,6,8…,不会出现10的倍数)
所以,求2的p次方减1的位数,可以转化为求2的p次方的位数: lg(2^p)+1
这样,我们就可以利用数学公式lg(m^n) = mlg(n)将: lg(2^p)+1 ----> plg(2)+1
这就简单很多了。()
//这个是dalao的博客
第二问难点就在高精度乘法 还有快速幂上
快速幂不会的赶紧去y总那看模板!!


#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
using namespace std;
int f[1001];//chengji
int p,res[1001],sav[1001];
void ult1()
{
    memset(sav,0,sizeof(sav));
    for(int i=1;i<=500;i++)
      for(int j=1;j<=500;j++)
        sav[i+j-1]+=res[i]*f[j];
        for(int i=1;i<=500;i++)
        {
            sav[i+1]+=sav[i]/10;
            sav[i]%=10;  //解决进位
        }
        memcpy(res,sav,sizeof(res));
}
void ult2()
{
    memset(sav,0,sizeof(sav));
    for(int i=1;i<=500;i++)
      for(int j=1;j<=500;j++)
        sav[i+j-1]+=f[i]*f[j];// 将乘积变大
        for(int i=1;i<=500;i++)
        {
            sav[i+1]+=sav[i]/10;
            sav[i]%=10;  //解决进位
        }
        memcpy(f,sav,sizeof(f));
}
int main()
{
    cin>>p;
    cout<<(int)(log10(2)*p+1)<<endl;
    res[1]=1;//初始化结果
    f[1]=2;
    while(p!=0)
    {
        if(p%2==1)  ult1();
        p/=2;
        ult2();
    }
    res[1]=res[1]-1;
    for(int i=500;i>=1;i--)

        if(i!=500&&i%50==0)  printf("\n%d",res[i]);
        else cout<<res[i];

    return 0;
}

这个题主要是注意细节就好了


第四题
表达式求值
while(scanf(“%d%[+]”,&a[n],&op[n])==2)n++;
/
一个非常好的用法,省了很多事
每次输入一个整数和一个符号,符号是在+和中选一个
scanf返回读到的个数,如果不是两个(说明只读到了最后一个整数)
到么字符串就结束了,停止读入,n记录一共有多少个数(共有n-1个符号)
/
我就想讲这一个(一个小trick)


https://www.acwing.com/problem/content/513/
联合权值
这个应该结合图片 但我不会上传 5555
这是一道统计题 首先就找特征
很明显 我们可以想到枚中间点来做这个题
第一问很容易解决 找到wx*wy最大的就好了
我们通过菊花图可以发现一个定理
我们要求的是 2wab+2wbc+2wcd+2wda
(a+b+c+d)²=a²+b²+c²+d²+a(b+c+d)+b(a+c+d)+c(a+b+d)+d(a+b+c)

移项得
(a+b+c+d)²-a²+b²+c²+d²=2wab+2wbc+2wcd+2wda
这就是我们想要的答案

#include<cstdio>
using namespace std;
struct edge
{
    int next;
    int to;
}a[400005];
int edgenum,head[200005],w[200005];
int n,ans,maxx;
void add(int u,int v)//加入一条从u到v的边
{
    a[++edgenum].next=head[u];
    a[edgenum].to=v;
    head[u]=edgenum;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<n;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        add(u,v);
        add(v,u);
    }
    for(int i=1;i<=n;i++)
      scanf("%d",&w[i]);
    for(int i=1;i<=n;i++)
    {
        int max1=0,max2=0;//最大的两个权值
        int t1=0,t2=0;//t1代表和的平方,t2代表平方和
        for(int j=head[i];j;j=a[j].next)
        {
            if(w[a[j].to]>max1)max2=max1,max1=w[a[j].to];
            else if(w[a[j].to]>max2)max2=w[a[j].to];
            t1=(t1+w[a[j].to])%10007;
            t2=(t2+w[a[j].to]*w[a[j].to])%10007;
        }
        t1=t1*t1%10007;
        ans=(ans+t1+10007-t2)%10007;
        if(maxx<max1*max2)maxx=max1*max2;
    }
    printf("%d %d\n",maxx,ans);
    return 0;
}

最后一道题 :魔法阵
根据这个xa<xb<xc<xd,xb−xa=2(xd−xc),并且xb−xa<(xc−xb)/3 时,画图就好

#include<cstdio>
using namespace std;
int n,m;
int v[40010],num[15010];
int a[15010],b[15010],c[15010],d[15010];
int main(){
    scanf("%d%d",&n,&m);
    for(int i = 1; i <= m; i ++){
        scanf("%d",&v[i]);
        num[v[i]]++;//桶排序
    }
    for(int t = 1; t * 9 < n; t++){ //枚举t
        int sum = 0;
        int va,vb,vc,vd;
        for(vd = t * 9 + 2; vd <= n; vd++){//枚举 d 物品的位置
            va = vd - 9 * t - 1;//a 物品的魔法值
            vb = vd - 7 * t - 1;//b 物品的魔法值
            vc = vd - t;//c 物品的魔法值
            sum += num[vb] * num[va]; //前缀和求能组成的魔法阵的个数
            c[vc] += num[vd] * sum;
            d[vd] += num[vc] * sum; 
        }
        sum = 0;
        for(va = n - t * 9 - 1; va >= 1; va--){//枚举 a 物品的位置
            vb = va + 2 * t;
            vc = va + t * 8 + 1;
            vd = va + t * 9 + 1;
            sum += num[vc] * num[vd];
            a[va] += num[vb] * sum;
            b[vb] += num[va] * sum;
        }
    }
    for(int i = 1; i <= m; i++)
        printf("%d %d %d %d\n", a[v[i]],b[v[i]],c[v[i]],d[v[i]]);
}

5 评论


用户头像
福如东海   2019-12-17 12:16         踩      回复

有个疑问 noip 能用 ios::sync_with_stdio(false) 吗, freopen后 需不需要fclose(stdin)?


用户头像
wzc1995   2019-09-15 03:30         踩      回复

建议把标题改为 NOIP 题目总结 之类的会更清晰~

用户头像
robot_1   2019-09-16 00:57         踩      回复

非常感谢!


用户头像
秦淮岸灯火阑珊   2019-09-08 18:47         踩      回复

好棒啊!

用户头像
robot_1   2019-09-16 00:57         踩      回复

谢谢!


App 内打开
你确定删除吗?
1024
x

© 2018-2025 AcWing 版权所有  |  京ICP备2021015969号-2
用户协议  |  隐私政策  |  常见问题  |  联系我们
AcWing
请输入登录信息
更多登录方式: 微信图标 qq图标 qq图标
请输入绑定的邮箱地址
请输入注册信息