POJ3489 Knapsack I

来源:互联网 发布:网络歌手算明星吗 编辑:程序博客网 时间:2024/05/21 10:15

题目链接:http://poj.org/problem?id=3489

题目描述:

给定n个数以及x,k,这n个数可以分成k^t( 0<=t )份,比如说其中一个数为6,k为4,可以分为6/4 = 1.5,或者分成6/(4^2) = 0.375,问这些数能否加起来和为x。

即满足:(假设n个数为t1….tn)

x1*(t1/(k^y1)) + x2*(t2/(k^y2))+…………xn*(tn/(k^yn)) = x

关键点就是:

有解的充要条件是,

x能够整除d,(其中d为n个数公约数除以其与k^t的公约数),其中t保证充分大。

推导过程不是很复杂(省略)

推荐一个有详细证明的:

http://www.cppblog.com/menjitianya/archive/2011/04/15/144291.html

#include<cstdio>#include<iostream>using namespace std ;const int MAXM = 100000 ;int num, pri[MAXM] ;int gcd(int a, int b){if( b == 0 ){return a ;}elsereturn gcd(b,a%b) ;}//int get(int n){num = 0 ;for( int i = 2; i*i <= n; i++ ){if( n % i == 0 ){pri[num++] = i ;}while( n % i == 0 ){n /= i ;}}if( n != 1 ) pri[num++] = n ;return num ;}///int main(){int n, x, k, temp, d = 0 ;bool res ;while( cin >> n >> x >> k ){d = 0 ;for( int i = 0; i < n; i++ ){scanf("%d",&temp) ;if( i == 0 )d = temp ;else{d = gcd(d,temp) ;} }get(k) ;res = true ;for( int i = 0; i < num; i++ ){while( d % pri[i] == 0 ){d /= pri[i] ;}}if( x % d != 0 )res = false ; if( res )cout << "Yes\n" ;elsecout << "No\n" ;}return 0 ;}




0 0
原创粉丝点击