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