看到了这道数学题,那么我们可以思考如何将这道题与程序联系起来。
(一)题目1
使用一个整数数组来初始化这样的一个加减封闭性集合,再输入一个整数x,判断整数x是否在生成的这个集合中。
解法:我们发现如果这个集合中存在1,则集合就是整数集。如果这个集合中存在元素x,则kx一定也在这个集合中。根据裴蜀定理,这个数组的元素进行有限次加减一定可以得到它们的最大公因数;而它们的最大公因数如果在这其中,这些元素也在集合中。因此,这道题就变成了求解数组的最大公因数,再判断整数x是否可以整除x。
我们有两种处理方法:
1.暴力解法
直接声明一个集合,根据题目中的描述进行处理。
#include <iostream>
#include <set>
#include <vector>
#include <queue>
using namespace std;
int main()
{
int n;
cin>>n;
vector<int> v(n);
for(int i=0; i<n; i++)
{
cin>>v[i];
}
set<int> s(v.begin(), v.end());
int x;
cin>>x;
if(s.find(x)!=s.end())
{
cout<<"YES"<<endl;
return 0;
}
queue<int> q;
for(int i=0; i<n; i++)
{
q.push(v[i]);
}
set<int> visited;
for(int i=0; i<n; i++)
{
visited.insert(v[i]);
}
while(!q.empty())
{
int t=q.front();
q.pop();
for(int i=0;i<n;i++)
{
int l=t-v[i];
int r=t+v[i];
if(l==x||r==x)
{
cout<<"YES"<<endl;
return 0;
}
if(visited.find(l)==visited.end())
{
q.push(l);
visited.insert(l);
}
if(visited.find(r)==visited.end())
{
q.push(r);
visited.insert(r);
}
}
}
cout<<"NO"<<endl;
return 0;
}
最坏的情况下的时间复杂度是。
2.辗转相除法
使用辗转相除法求解最大公约数。
#include <iostream>
#include <vector>
using namespace std;
int gcd(int x, int y)
{
if(y==0)
{
return x;
}
return gcd(y, x%y);
}
int main()
{
int n;
cin>>n;
vector<int> v(n);
for(int i=0; i<n; i++)
{
cin>>v[i];
}
int x;
cin>>x;
int res=v[0];
for(int i=1;i<n;i++)
{
res=gcd(res,v[i]);
}
if(x%res==0)
{
cout<<"YES"<<endl;
}
else
{
cout<<"NO"<<endl;
}
return 0;
}
时间复杂度接近于。
(二)题目2
如果将取值范围从整数扩展到浮点类型,如何处理?
解法:我们考虑是否可以使用相似的方法,但我们发现这是小数,于是我们可以将它们转化为整数。将这多个浮点数的小数点同时右移,直到所有数据都变为整数,此时就可以使用上述的判断方法了。
1.暴力解法
我们需要考虑精度问题,我们可以将输入数据的小数点同时向右移直到全部都变为整数,再使用整数方法进行处理。
2.辗转相除法
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
int gcd(int x, int y)
{
if(y==0)
{
return x;
}
return gcd(y, x%y);
}
int main()
{
int n;
cin>>n;
string s;
vector<int> v1(n,0);
int len=0;
int t;
vector<int> l(n);//每个的长度
for(int i=0; i<n; i++)
{
t=0;
cin>>s;
for(int j=0;j<s.size();j++)
{
if(s[j]=='.')
{
t=j;
continue;
}
v1[i]=v1[i]*10+s[j]-'0';
}
l[i]=s.size()-1-t;
len=max(len,l[i]);
}
cin>>s;
int x=0;
int xl=0;
for(int i=0;i<s.size();i++)
{
if(s[i]=='.')
{
t=i;
continue;
}
x=x*10+s[i]-'0';
}
xl=s.size()-1-t;
vector<int> v2(n);
for(int i=0; i<n; i++)
{
v2[i]=v1[i]*pow(10,len-l[i]);
}
int res=v2[0];
for(int i=1;i<n;i++)
{
res=gcd(res,v2[i]);
}
if(xl<=len)
{
x=x*pow(10,len-xl);
if(x%res==0)
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
else
{
cout<<"NO"<<endl;
}
return 0;
}
还使用了字符串方法防止了浮点精度的影响。