ALGO-10. 集合运算
问题描述
给出两个整数集合A、B,求出他们的交集、并集以及B在A中的余集。
输入格式
第⼀行为⼀个整数n,表示集合A中的元素个数。
第⼆行有n个互不相同的⽤用空格隔开的整数,表示集合A中的元素。
第三行为⼀个整数m,表示集合B中的元素个数。
第四⾏行行有m个互不不相同的⽤用空格隔开的整数,表示集合B中的元素。
集合中的所有元素均为int范围内的整数,n、m<=1000。
输出格式
第⼀行行按从⼩到大的顺序输出A、B交集中的所有元素。
第⼆行行按从小到大的顺序输出A、B并集中的所有元素。
第三行按从⼩到大的顺序输出B在A中的余集中的所有元素。
样例例输⼊入
5
1 2 3 4 5
5
2 4 6 8 10
样例例输出
2 4
1 2 3 4 5 6 8 10
1 3 5
样例例输⼊入
4
1 2 3 4
3
5 6 7
样例例输出
1 2 3 4 5 6 7
1 2 3 4
只用数组进行暴力运算:
#include<iostream>
#include<algorithm>
#define max(a,b) a>=b?a:b;
#define min(a,b) a<=b?a:b;
using namespace std;
int a[1000],b[1000];
int c[2000];
int main(){
int n,m;
cin>>n;
for(int i=0;i<n;i++)
cin>>a[i];
cin>>m;
for(int j=0;j<m;j++)
cin>>b[j];
sort(a,a+n);
sort(b,b+m);
int s=0;
for(int i=0;i<=n;i++)
{
for(int j=0;j<m;j++)
{
if(a[i]==b[j])
{c[s++]=b[j];
break;
}
}
}
for(int i=0;i<s;i++)
cout<<c[i]<<" ";
cout<<endl;
int p=0;
for(int i=0;i<n;i++)
{
int flag=1;
for(int j=0;j<s;j++)
if(a[i]==c[j])
{
flag=0;
break;
}
if(flag){ b[m+p]=a[i];
p++; }
}
sort(b,b+n+m-s);
for(int i=0;i<n+m-s;i++)
cout<<b[i]<<" ";
cout<<endl;
s=0;
for(int i=0;i<n;i++)
{
if(a[i]!=c[s])
{
cout<<a[i]<<" ";
}
else s++;
}
return 0;
}
思考:
1、利用map,第⼀一个集合的元素标记为1,第⼆二个集合的元素累加2
2.判断,值为1的为余集,有值的为交集,值为3的为并集,且map⾃带排序功能~
#include<iostream>
#include<map>
using namespace std;
int main(){
int n,m,t;
map<int,int>a;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>t;
a[t]=1;//键:t,值:1
}
cin>>m;
for(int i=0;i<n;i++)
{
cin>>t;
a[t]+=2;//键:t,值:1
}
for(auto it=a.begin();i!=a.end();i++)
if(it->second==3) cout<<it->first<<" ";
cout<<endl;
for(auto it=a.begin();i!=a.end();i++)
if(it->second>0) cout<<it->first<<" ";
cout<<endl;
for(auto it=a.begin();i!=a.end();i++)
if(it->second==1) cout<<it->first<<" ";
cout<<endl;
return 0;
}
看完大佬的做法,简直了!
ALGO-11. 瓷砖铺放(递归/动态规划)
问题描述
有⼀一⻓长度为N(1<=N<=10)的地板,给定两种不不同瓷砖:⼀一种⻓长度为1,另⼀一种⻓长度为2,数⽬目不不
限。要将这个⻓长度为N的地板铺满,⼀一共有多少种不不同的铺法?
例例如,⻓长度为4的地⾯面⼀一共有如下5种铺法:
4=1+1+1+1
4=2+1+1
4=1+2+1
4=1+1+2
4=2+2
编程⽤用递归的⽅方法求解上述问题。
输⼊入格式
只有⼀一个数N,代表地板的⻓长度
输出格式
输出⼀一个数,代表所有不不同的瓷砖铺放⽅方法的总数
样例例输⼊入
4
样例例输出
5
思考:
线性模型一般用动态规划解决
最佳解决方案a[i]都可以通过a[i-1]或者a[i-2]得出想要的结果。例如样例中长度为4,f(4)=f(3 )+1;f(4)=f(2 )+2只需要求f(2)\f(3)即可
#include<iostream>
#include<vector>
using namespace std;
int main(){
int n;
cin>>n;
int count;
vector<int> v(n+1);
v[0]=1,v[1]=1;
for(int i=2;i<n;i++)
{
v[i]=v[i-1]+v[i-2];
}
cout<<v[n];
return 0;
}
ALGO-12. 幂方分解!
问题描述
任何⼀一个正整数都可以⽤用2的幂次⽅方表示。例例如:
137=27+23+20
同时约定⽅方次⽤用括号来表示,即ab 可表示为a(b)。
由此可知,137可表示为:
2(7)+2(3)+2(0)
进⼀一步:7= 22+2+20 (21⽤用2表示)
3=2+20
所以最后137可表示为:
2(2(2)+2+2(0))+2(2+2(0))+2(0)
⼜又如:
1315=210 +28 +25 +2+1
所以1315最后可表示为:
2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)
输⼊入格式
输⼊入包含⼀一个正整数N(N<=20000),为要求分解的整数。
输出格式
程序输出包含⼀一⾏行行字符串串,为符合约定的n的0,2表示(在表示中不不能有空格)
#include<iostream>
#include<vector>
using namespace std;
string dfs(int n){
if(n==1) return "1";
if(n==0) return "0";
vector<int> v;
int count;
string ans;
while(n){
if(n%2==1) v.push_back(count);
n/=2;
count++;
}
for (int i = v.size() - 1; i >= 0; i--) {
ans += "2(" + dfs(v[i]) + ")";
if (i != 0) ans += "+";
}
return ans;
}
int main(){
int n;
cin>>n;
string ans=dfs(n);
for(int i=0;i<ans.size();i++)
{
if(ans[i+1]=='1')
i+=3;
cout<<ans[i];
}
return 0;
}
这道题就很烦
ALGO-14. 回⽂文数!
问题描述
若⼀一个数(⾸首位不不为零)从左向右读与从右向左读都⼀一样,我们就将其称之为回⽂文数。
例例如:给定⼀一个10进制数56,将56加65(即把56从右向左读),得到121是⼀一个回⽂文数。
⼜又如:对于10进制数87:
STEP1:87+78 = 165
STEP2:165+561 = 726
STEP3:726+627 = 1353
STEP4:1353+3531 = 4884
在这⾥里里的⼀一步是指进⾏行行了了⼀一次N进制的加法,上例例最少⽤用了了4步得到回⽂文数4884。
写⼀一个程序,给定⼀一个N(2<=N<=10或N=16)进制数M(其中16进制数字为0-9与A-F),求最少经
过⼏几步可以得到回⽂文数。
如果在30步以内(包含30步)不不可能得到回⽂文数,则输出“Impossible!”
输⼊入格式
两⾏行行,N与M
输出格式
如果能在30步以内得到回⽂文数,输出“STEP=xx”(不不含引号),其中xx是步数;否则输出⼀一
⾏行行”Impossible!”(不不含引号)
样例例输⼊入
9
87
样例例输出
STEP=6
#include<iostream>
#include<vector>
#include<bits/stdc++.h>
using namespace std;
int n;
vector<int > f(vector<int> v){
vector<int>v1(v),v2(v),ans(v.size(),0);
reverse(v2.begin(),v2.end());//v2反置
int temp=0;
for(int i=v.size()-1;i>=0;i--)
{
ans[i]=(v1[i]+v2[i]+temp)%n;
temp=(v1[i]+v2[i]+temp)/n;
}
if(temp>0)
ans.insert(ans.begin(),temp);
return ans;
}
bool is(vector<int> v)
{
for(int i=0;i<v.size();i++)
if(v[i]!=v[v.size()-i-1])
return false;
return true;
}
int main(){
string m;
cin>>n>>m;
vector<int> v;
for(int i=0;i<m.size();i++)
if(m[i]>='0'&&m[i]<'10') v.push_back(m[i]-'0');
else if(m[i]>='A'&&m[i]<='F') v.push_back(m[i]-'A'+10);
int cnt=0;
// cout<<"111";
while(!is(v)){
v=f(v);
cnt++;
if(cnt==30)
{
cout<<"Impossible!";
return 0;
}
}
cout<<"STEP="<<cnt;
return 0;
}
思考:
1、可以用vector的转置,vector的复制数组
2、由于有16进制(超过10了)所以用的是vector动态数组而不是string