NOIP2001普及组

前言

因为NOIP原题各大OJ上都是有的,本博客不再重复粘贴题目的工作,只写下题解和AC程序。

 

第一题 数的计算

递归写即可。

 

第二题 最大公约数和最小公倍数

设p1 = p / x0, q1 = q / x0。因为x0是最大公约数,所以p1,q1互质。又因为y0 = pq / x0。有p1q1 = y0 / x0。

设s = y0 / x0。即求p1q1 = s且p1,q1互质的解数。

将s分解质因数。因为p1,q1互质,所以两数不会有相同的质因数。那么p1,q1的解数就是s的质因数个数k的2的幂。

即ans = 2 ^ k。

 

第三题 求先序排列

设a是中序遍历,b是后序遍历。a[l]…a[r]对应b[x]…b[y]。那么b[y]是这颗子树的根节点,将其输出。设a[i] = b[y](l <= i <= r)。那么左子树的节点个数是i – l – 1。b[x]中从x开始i – l - 1长度的是左子树的后续遍历。a[l]…a[i]是左子树的中序遍历。b[x]中除去左子树后根节点的那段是右子树。a[x]中a[i + 1]…a[r]是右子树。分别递归处理。

 

第四题 装箱问题

01背包。详见《背包九讲》。

 

代码

第一题

#include <stdio.h>

int n,ans;

void find(int x) {

  for (int i = 1;i <= x / 2;++i) {

    ++ans;

    find(i);

  }

}

int main() {

  scanf("%d",&n);

  ans = 1;

  find(n);

  printf("%d\n",ans);

  return 0;

}

第二题

#include <stdio.h>

long long p,t,x,y,ans,k;

int main() {

  scanf("%lld%lld",&x,&y);

  if (y % x) {

    printf("0\n");

    return 0;

  }

  p = y / x;

  t = 2;

  while (p > 1) {

    if (p % t == 0) {

      ++k;

      while (p % t == 0)

        p /= t;

    }

    ++t;

  }

  ans = 2;

  for (int i = 1;i < k;++i)

    ans *= 2;

  printf("%lld\n",ans);

  return 0;

}

第三题

#include <stdio.h>

#include <string.h>

#define MAXN 10

char a[MAXN],b[MAXN];

void find(int l,int r,int x,int y) {

  if (l > r)

    return;

  printf("%c",b[y]);

  if (l == r)

    return;

  for (int i = l;i <= r;++i)

    if (a[i] == b[y]) {

      find(l,i - 1,x,x + i - l - 1);

      find(i + 1,r,x + i - l,y - 1);

      return;

    }

}

int main() {

  scanf("%s%s",a,b);

  int len = strlen(a);

  find(0,len - 1,0,len - 1);

  return 0;

}

第四题

#include <stdio.h>

#define MAXV 20010

int f[MAXV],v,w,n;

int main() {

  scanf("%d%d",&v,&n);

  for (int i = 1;i <= n;++i) {

    scanf("%d",&w);

    for (int j = v;j >= w;--j)

      if (f[j] < f[j - w] + w)

        f[j] = f[j - w] + w;

  }

  printf("%d\n",v - f[v]);

  return 0;

}

你可能感兴趣的:(IP)