NOIP 2001 数的划分 解题报告

  我直接模拟的,第i个数字必定大于或等于第i-1个数字,我是按照这种思想模拟的,那么每种情况就只会考虑一次,然后需要一个重大剪枝:

  当i=k-1的时候,就不去枚举了,直接得到答案,用n-sum,我还有一个小剪枝,因为我的第i个数一定大于或等于第i-1个数,那么如果第i个数加到第k个数就大于n的话,就没必要继续枚举了。

  2011年08月29日:
    刚刚发现,上次的代码有问题,数据太弱,所以过了,但是2 15 151,2 151 15的答案不一样,思索了好久,最后想出了正确的算法。
    就是枚举两个字符串,如果相同就继续枚举,不同就继续枚举。。。。。(没听懂的看下面第二段代码,第一段只能AC不是正确。。)
 

  代码:

#include <stdio.h>
#include <stdlib.h>
int n, k;
int ans;

void srch(int deep, int now, int sum)
{
	int i;
	if(deep == k){
		if(sum == n){
			ans++;
		}
		return;
	}
	if(deep == k - 1){
		srch(deep + 1, n - sum, n);
		return;
	}
	for(i = now; i <= n - sum; i++){
		if(sum + (k - deep) * i > n){
			return;
		}
		srch(deep + 1, i, sum + i);
	}
}

int main(int argc, char **argv)
{
	int i;
	scanf("%d%d", &n, &k);
	for(i = 1; i <= n; i++){
		if(k * i <= n){
			srch(1, i, i);
		}
	}
	printf("%d\n", ans);
	return 0;
}

  

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char str[20][10001];

int gcd(int a, int b)
{
	int t;
	while(b != 0){
		t = b;
		b = a % b;
		a = t;
	}
	return a;
}

int com(const void *a, const void *b)
{
	char *s1 = (char *)a, *s2 = (char *)b;
	int t, s;
	int l1 = strlen(s1), l2 = strlen(s2);
	s = l1 / gcd(l1, l2) * l2;
	for(t = 0; t < s; t++){
		if(s1[t % l1] != s2[t % l2]){
			return s2[t % l2] - s1[t % l1];
		}
	}
	return 0;
}

int main(int argc, char **argv)
{
	int i;
	int n;
	scanf("%d", &n);
	for(i = 0; i < n; i++){
		scanf("%s", str[i]);
	}
	qsort(str, n, sizeof(char) * 10001, com);
	for(i = 0; i < n; i++){
		printf("%s", str[i]);
	}
	printf("\n");
	return 0;
}

  

posted @ 2011-08-17 23:43  zqynux  阅读(326)  评论(0编辑  收藏  举报