现在的位置: 首页 > 综合 > 正文

NOIP2001普及组

2013年06月05日 ⁄ 综合 ⁄ 共 1349字 ⁄ 字号 评论关闭

前言

因为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;
}

抱歉!评论已关闭.