题意:给出二元一次函数式的a,b,c问该式子能否被因式分解,十字交叉法,直接暴力
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define LL __int64
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
LL a,b,c;
scanf("%I64d %I64d%I64d",&a,&b,&c);
bool sign=false;
if((b*b-4*a*c)<0)
printf("NO\n");
else
{
for(int i=1;i<=sqrt(a);i++)
{
for(int j=1;j<=sqrt(c);j++)
{
if((a%i==0)&&(c%j==0))
{
LL k,q,m,p;
p=i,q=a/i,k=j,m=c/j;
if((q*k+m*p==b)||(m*q+p*k==b))
{
sign=true;
break;
}
}
}
if(sign==true)
break;
}
if(sign==true)
printf("YES\n");
else
printf("NO\n");
}
}
return 0;
}
解题思路:01背包的思想。如果全部砝码放在右边那么最重可以有2000个重量,左右都可以放,将2000作为平衡点,DP方程如下:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=25;
const int maxm=4000+5;
int dp[maxn][maxm];//maxn代表砝码的总数量,以2000为平衡点
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
int sum=0;
int weight[25];
for(int i=1;i<=n;i++)
{
scanf("%d",&weight[i]);
sum+=weight[i];
}
memset(dp,0,sizeof(dp));
dp[0][2000]=1;//以2000为平衡点,设dp[i][j]表示用了i个砝码称j重量是否可行
for(int i=1;i<=n;i++)
{
for(int j=4000;j>=0;j--)
{
if(dp[i-1][j]) //转移一,如果只用了i-1个砝码就称出了j,那么多加一个砝码也足够称出j
dp[i][j]=1;
if(j+weight[i]<=4000 && dp[i-1][j])
dp[i][j+weight[i]]=1; //转移二,如果用i-1个砝码称出了j,那么我在右边多加一个砝码,就可以称出j+w[i]
if(j-weight[i]>=2000 && dp[i-1][j])
dp[i][j-weight[i]]=1; //转移三,如果用i-1个砝码称出了j,那么我在左边多加一个砝码,就可以称出j-w[i]
}
}
int Case;
scanf("%d",&Case);
while(Case--)
{
int x;
scanf("%d",&x);
if(!dp[n][x + 2000] || x>sum)
printf("NO\n");
else
printf("YES\n");
}
}
return 0;
}