题目
思路
考场80分:
- 先从小到大sort,因为小的才可以组成大的
- 设一标记数组,记录当前i能不能被组成
- 遍历纸币,判断当前x这张纸币能否被之前选了的纸币组成,不能组成ans就++:再在标记数组里,把k倍x纸币设为true,遍历标记数组,当当前i可以被组成,那么i+k倍x也可以组成,设为true
- 然后·······就WA了四个点(
wdnmd)
不信你能找出错!
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
#define N 300005
int T,n;
int a[105];
bool v[N],last;
void Solve_3(){
memset(v,0,sizeof(v));
int ans = 1;
for(int i=1; i*a[1]<=a[n]; i++)
v[a[1]*i] = true;
for(int i=2; i<=n; i++){
bool find1 = false,find2 = false,update = false;
if(v[a[i]] == true) //1th condition (a+a)
find1 = true;
if(!find1){
for(int j=1; 2*j<=a[n]; j++)//2th condition (a+b)
if(v[j] && v[a[i]-j]){
find2 = true;
update = true;
break;
}
}
if(!find1 && !find2) {ans++;update = true;}
if(update){
/*for(int j=1; j*a[i]<=a[n]; j++)
v[a[i]*j] = true;*/
for(int k=1; k*a[i]<=a[n]; k++){
v[k*a[i]] = true;
for(int j=1; j<=a[n]; j++)
if(v[j]) v[j+k*a[i]] = true;
}
}
}
printf("%d\n",ans);
}
int main()
{
// freopen("money.in","r",stdin) ;
// freopen("money.out","w",stdout);
scanf("%d",&T);
while(T--){
last=false;
if(T==0) last = true;
scanf("%d",&n);
for(int i=1; i<=n; i++)
scanf("%d",&a[i]);
sort(a+1,a+1+n);
if(a[1] == 1) {printf("1\n");continue;}
Solve_3();
}
return 0;
}
正解
设置一v数组,答案要选的纸币为2,可以被选的纸币所组成的为1,不能被组成的为0
(easy,why i did not ma chu lai)
include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
#define N 250005
int T,n,ans;
int a[105];
int v[N];
void Solve(){
ans = 0;
for(int i=1; i<=a[n]; i++)
if(v[i])
for(int j=1; i+a[j]<=a[n]; j++)
v[i+a[j]] = 1;
for(int i=1; i<=a[n]; i++)
if(v[i] == 2) ans++;
printf("%d\n",ans);
}
int main()
{
// freopen("testdata.in","r",stdin) ;
// freopen("money.out","w",stdout);
scanf("%d",&T);
while(T--){
memset(v,0,sizeof(v));
scanf("%d",&n);
for(int i=1; i<=n; i++){
scanf("%d",&a[i]);
v[a[i]] = 2;
}
sort(a+1,a+1+n);
if(a[1] == 1) {printf("1\n");continue;}
Solve();
}
return 0;
}