USACO section 3.1 Humble Numbers(DP)

Humble Numbers

For a given set of K prime numbers S = {p1, p2, ..., pK}, consider the set of all numbers whose prime factors are a subset of S. This set contains, for example, p1, p1p2, p1p1, and p1p2p3 (among others). This is the set of `humble numbers' for the input set S. Note: The number 1 is explicitly declared not to be a humble number.

Your job is to find the Nth humble number for a given set S. Long integers (signed 32-bit) will be adequate for all solutions.

PROGRAM NAME: humble

INPUT FORMAT

 

Line 1: Two space separated integers: K and N, 1 <= K <=100 and 1 <= N <= 100,000.
Line 2: K space separated positive integers that comprise the set S.

SAMPLE INPUT (file humble.in)

4 19
2 3 5 7

OUTPUT FORMAT

The Nth humble number from set S printed alone on a line.

SAMPLE OUTPUT (file humble.out)

27

思路:如果已知前n个丑数要求第n+1个,就只要把集合中的素数依次乘上前n个丑数找到大于第n个丑数的最小的数即是第n+1个丑数;

         不过要是这样直接写绝对爆。优化:用个数组num[];存第i个素数遍历到了第几个丑数,下次只要接着走就行了。

失误点:答案有大于1e9的数,所以const oo=1e9;会错,就是这个提交WA了一次,要用1e10; 

具体看代码:

 

/*
ID:nealgav1
LANG:C++
PROG:humble
*/
#include<fstream>
#include<cstring>
using namespace std;
ifstream cin("humble.in");
ofstream cout("humble.out");
const int oo=1e10;
const int mm=101000;
const int nn=110;
int prime[nn],num[mm],pos[nn];
int main()
{ int m,n;
  cin>>m>>n;
  memset(num,1,sizeof(num));
  memset(pos,0,sizeof(pos));
  for(int i=0;i<m;i++)
  cin>>prime[i];
  int Max,k,last,mid;
  num[0]=1;
  for(int j=1;j<=n;j++)
  { num[j]=oo;//cout<<Max<<"\n";
    for(int i=0;i<m;i++)
    {  for(int l=0;pos[i]<=j;l++)
       {
         mid=prime[i]*num[pos[i]];
         if(num[j-1]>=mid)pos[i]++;
         else break;
       }
       if(num[j-1]<mid)
       { if(num[j]>mid)
         {num[j]=mid;k=i;}

       }
    }pos[k]++;
  }
  cout<<num[n]<<"\n";
}


 

Humble Numbers
Russ Cox

We compute the first n humble numbers in the "hum" array. For simplicity of implementation, we treat 1 as a humble number, and adjust accordingly.

Once we have the first k humble numbers and want to compute the k+1st, we do the following:

	for each prime p
		find the minimum humble number h
		  such that h * p is bigger than the last humble number.

	take the smallest h * p found: that's the next humble number.

To speed up the search, we keep an index "pindex" of what h is for each prime, and start there rather than at the beginning of the list.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <ctype.h>

#define MAXPRIME 100
#define MAXN 100000

long hum[MAXN+1];
int nhum;

int prime[MAXPRIME];
int pindex[MAXPRIME];
int nprime;

void
main(void)
{
    FILE *fin, *fout;
    int i, minp;
    long min;
    int n;

    fin = fopen("humble.in", "r");
    fout = fopen("humble.out", "w");
    assert(fin != NULL && fout != NULL);

    fscanf(fin, "%d %d", &nprime, &n);
    for(i=0; i<nprime; i++)
	fscanf(fin, "%d", &prime[i]);

    hum[nhum++] = 1;
    for(i=0; i<nprime; i++)
	pindex[i] = 0;

    while(nhum < n+1) {
	min = 0x7FFFFFFF;
	minp = -1;
	for(i=0; i<nprime; i++) {
	    while((double)prime[i] * hum[pindex[i]] <= hum[nhum-1]) 
		pindex[i]++;

	    /* double to avoid overflow problems */
	    if((double)prime[i] * hum[pindex[i]] < min) {
		min = prime[i] * hum[pindex[i]];
		minp = i;
	    }
	}

	hum[nhum++] = min;
	pindex[minp]++;
    }

    fprintf(fout, "%d\n", hum[n]);
    exit(0);
}
 

 

 

USER: Neal Gavin Gavin [nealgav1]
TASK: humble
LANG: C++

Compiling...
Compile: OK

Executing...
   Test 1: TEST OK [0.000 secs, 3752 KB]
   Test 2: TEST OK [0.000 secs, 3752 KB]
   Test 3: TEST OK [0.000 secs, 3752 KB]
   Test 4: TEST OK [0.000 secs, 3752 KB]
   Test 5: TEST OK [0.011 secs, 3752 KB]
   Test 6: TEST OK [0.032 secs, 3752 KB]
   Test 7: TEST OK [0.011 secs, 3752 KB]
   Test 8: TEST OK [0.011 secs, 3752 KB]
   Test 9: TEST OK [0.000 secs, 3752 KB]
   Test 10: TEST OK [0.000 secs, 3752 KB]
   Test 11: TEST OK [0.000 secs, 3752 KB]
   Test 12: TEST OK [0.086 secs, 3752 KB]

All tests OK.

Your program ('humble') produced all correct answers! This is your submission #2 for this problem. Congratulations!

Here are the test data inputs:

------- test 1 ----
2 7
3 5
------- test 2 ----
4 19
2 3 5 7
------- test 3 ----
1 20
2
------- test 4 ----
6 10000
2 3 5 7 11 13
------- test 5 ----
6 25000
2 3 5 7 11 13
------- test 6 ----
8 100000
2 3 5 7 11 13 17 19
------- test 7 ----
7 30000
2 3 5 7 11 17 23
------- test 8 ----
7 28888
2 3 5 11 17 23 31
------- test 9 ----
1 30
2
------- test 10 ----
4 300
11 17 23 31
------- test 11 ----
5 300
11 17 19 23 31
------- test 12 ----
100 100000
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199 211 223 227 229 233 239 241 251 257 263 269 271 277 281 283 293 307 311 313 317 331 337 347 349 353 359 367 373 379 383 389 397 401 409 419 421 431 433 439 443 449 457 461 463 467 479 487 491 499 503 509 521 523 541

 

你可能感兴趣的:(USACO section 3.1 Humble Numbers(DP))