https://www.luogu.org/problemnew/show/P2737
给出n个数ai,求这n个数不能累加出的最大的数
最大的数无限大或能凑出所有的自然数则输出0
n<=10,ai<=256
结论一:
给出两个数a,b
若a,b 能凑出大于某个数的所有自然数
那么由a的倍数组成的数必定能构成模b的完全剩余系
否则 由a的倍数组成的数 不能构成模b的完全剩余系
证明:
若由a的倍数组成的数能构成模b的完全剩余系
那么存在 k1,k2,…… kb 满足 ki*a%b 互不相同
即 ax-by=p
对于 任意的p∈[0,b-1] 一定有x,y 的非负整数解
而由扩展欧几里得定理得
若gcd(a,b)= d
则 ax+by=k*d 一定有整数解,
且一定存在一组解,满足x∈[0,b/d-1],y∈[-a/d+1,0]
所以
若a,b互质,即gcd(a,b)= 1 ,p 必定是1的倍数,所以 由x个a,-y个b,可以凑出%b=p,p∈[0,b-1]的任意数
若a,b不互质,则gcd(a,b)= d,那么只能凑出满足p%d=0 的数
结论二:
若gcd(a,b)=1 ,那么由a,b 不能凑出的最大的数为 a*b-a-b
证明:
1、 由结论一得,a,b 一定存在不能凑出的最大的数
2、证明这个最大的数为 a*b-a-b,即noip2017 day1 t1
所以本题解法:
先判断给出的n个数gcd是否等于1,不等于1则不等凑出的数无穷大,输出0
然后dp[i] 表示数i能否被凑出来,做一遍完全背包即可
从里面找出不能凑出的最大的数
#include<cstdio>
using namespace std;
#define N 256*256
bool dp[N+1];
int a[11];
int getgcd(int a,int b) { return !b ? a : getgcd(b,a%b); }
int main()
{
int n;
scanf("%d",&n);
int gcd=0;
for(int i=1;i<=n;++i)
{
scanf("%d",&a[i]);
gcd=getgcd(a[i],gcd);
}
if(gcd!=1)
{
printf("0");
return 0;
}
dp[0]=true;
for(int i=1;i<=n;++i)
for(int j=a[i];j<N;++j)
dp[j]|=dp[j-a[i]];
for(int i=N-1;i>=0;--i)
if(!dp[i]) { printf("%d",i); return 0; }
printf("0");
}
作者:xxy
















