题目是输入一个数字,分解成三个数字的和,这三个数字都不相同,并且都不可以被三整除,如果存在输出YES并且输出任意一组可能的三个数字,否则输出NO
#include
using namespace std;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int x,y,z;
int n;
bool flag=false;
scanf("%d",&n);
for(x=1;x<=10;x++)
{
for(y=x+1;y<=10;y++)
{
z=n-x-y;
if(x%3!=0&&y%3!=0&&z%3!=0&&z>y)
{
printf("YES\n%d %d %d\n",x,y,z);
flag=true;
break;
}
}
if(flag==true) break;
}
if(!flag) printf("NO\n");
}
return 0;
}
循环,让第二个数字y等于x+1就可以保证最开始两个数字就不相等,还是这种方法最明了,直接条件判断
#include
using namespace std;
int ans[5];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
bool flag=false;
scanf("%d",&n);
int temp=n/3;
if(n%3==0)
{
if(temp%3!=0)
{
ans[0]=temp-1,ans[1]=temp,ans[2]=temp+1;
while((ans[0]%3==0||ans[2]%3==0)&&ans[0]>0)
{
ans[0]-=1;
ans[2]+=1;
}
}
else
{
ans[0]=temp,ans[1]=temp-1,ans[2]=temp+1;
while((ans[0]%3==0||ans[2]%3==0||ans[0]==ans[1])&&ans[0]>0)
{
ans[0]-=1;
ans[2]+=1;
}
}
if(ans[0]+ans[1]+ans[2]==n&&ans[0]%3!=0&&ans[2]%3!=0&&ans[1]%3!=0&&ans[0]!=ans[1]&&ans[0]!=ans[2]&&ans[1]!=ans[2]) flag=true;
}
else
{
int q=n%3;
ans[0]=temp,ans[1]=temp,ans[2]=temp+q;
if(temp%3!=0)
{
ans[0]=temp,ans[1]=temp,ans[2]=temp+q;
while((ans[0]%3==0||ans[2]%3==0||ans[0]==ans[1])&&ans[0]>0)
{
ans[0]-=1;
ans[2]+=1;
}
}
else
{
ans[0]=temp-1,ans[1]=temp+1,ans[2]=temp+q;
while((ans[0]%3==0||ans[2]%3==0||ans[0]==ans[1]||ans[1]==ans[2])&&ans[0]>0)
{
ans[0]-=1;
ans[2]+=1;
}
}
if(ans[0]+ans[1]+ans[2]==n&&ans[0]%3!=0&&ans[2]%3!=0&&ans[1]%3!=0&&ans[0]!=ans[1]&&ans[0]!=ans[2]&&ans[1]!=ans[2]) flag=true;
}
if(n<=3) flag=false;
if(flag==true)
{
printf("YES\n");
printf("%d %d %d\n",ans[0],ans[1],ans[2]);
}
else printf("NO\n");
}
return 0;
}
标签是暴力破解,构造算法,数学
仔细想了一下,确实暴力就可以直接过
我比赛的时候想的方法确实比较繁琐哈哈
讨论输入的数字n是否能够被3整除,把数字n除以3,然后把这三个数字放在ans[0],ans[1],ans[2]里面,保证中间的位置满足不被3整除,然后调整ans[0],ans[2]这两个数字,ans[0]--,ans[2]++,一个因子减少一,另一个因子增加一,和n保持不变,所以可以满足条件,也可以寻找到答案
#include
using namespace std;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
if(n%3==0)
{
int z=n-5;
if(z%3!=0&&z>4) printf("YES\n1 4 %d\n",z);
else printf("NO\n");
}
else
{
int ans=n-3;
if(ans%3!=0&&ans>2) printf("YES\n1 2 %d\n",ans);
else printf("NO\n");
}
}
return 0;
}
上面这种做法是找规律,我们只需要输出一种符合条件的情况即可,所以我们考虑一些特殊的数字,比如说1和2,这两个数字不相同并且两个数字的和是3,如果数字n是可以被3整除的,并且大于3的话(如果是3的话,剩下的那个数字只可以是0,不符合条件),剩下的那个数字就一定可以被3整除,但是如果n不可以被3整除,剩下的那个数也不可以被3整除(如果可以被3整除的话,n就可以被3整除了)
有点绕
分两种特殊情况来考虑,第一种特殊情况,取x=1,y=2,这个时候假设n是不能被3整除的数字,剩下的那个数字我们记为z,z一定是不能被3整除的,因为假设z可以被3整除,加上3还是可以被3整除(加上3就等于n了),和假设矛盾,所以z一定不能被3整除(反证法),注意需要满足z大于2这个条件
第二种情况就是取x=1,y=4,考虑n可以被3整除,剩下的数字z一定是不可以被3整除的,证明如下,还是反证法,就是假设z是可以被3整除的,假设z=3b,n=3k,那么有5+3b=3k,移向可以得到5/3=k-b,两个整数的差不可能是小数,所以矛盾,所以z一定是不可以被3整除的
#include
using namespace std;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
if(n%3==0)
{
int z=n-5;
if(z>4) printf("YES\n1 4 %d\n",z);
else printf("NO\n");
}
else
{
int ans=n-3;
if(ans>2) printf("YES\n1 2 %d\n",ans);
else printf("NO\n");
}
}
return 0;
}
经过一通分析之后发现这样子其实更加简洁,但是前期需要分析的更多一些