目录
1.蓝桥幼儿园
2.找素数
3.优秀的拆分
4.蓝肽子序列
5.包子凑数
1.蓝桥幼儿园
解题思路,这题考察的是并查集,并查集模板题。
#include
using namespace std;
const int N =200010;
int n,m;
int p[N];//FATHER 数组存每个元素的父节点是谁,
int find(int x)//返回x的祖宗节点+路径压缩
{
if(p[x]!=x) p[x]=find(p[x]);//如果x不是根节点的话,我们就让他的父节点等于他的祖宗节点
return p[x];//返回他的父节点
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)p[i]=i;
while( m--)
{
int op, a,b;
scanf("%d%d%d",&op,&a,&b);
if(op==1)p[find(a)]= find(b);
else
{
if(find(a) == find(b)) cout<<"YES"<
2.找素数
题解:直接暴力筛素数,
#include
using namespace std;
bool is_prime(int n)
{
for(int i=2;i<=sqrt(n);i++)
{
if(n%i==0)
{
return 0;
}
}
return 1;
}
int main()
{
int cnt=0,sum=1;
while(cnt!=100002)
{
sum++;
if(is_prime(sum))
{
cnt++;
}
}
cout<
3.优秀的拆分
4.蓝肽子序列这题考察的是位运算。
#include
using namespace std; int main() { long long n; cin>>n; if(n&1)//把n的最后一位判断是否=1,如果等于1则不存在 { cout<<"-1"< 0;i--) { if((n>>i)&1)//把n右移i位,然后再与1,如果等于一说明该拆分方案成立 { cout<<(int)pow(2,i)<<" ";//pow函数默认返回值为double类型,求的是2^i } } return 0; }
题解思路:这题就是变种的最长公共子序列,用dp做,注意这题每个蓝肽的首字母都是大写,然后后面都是小写,用两个数组分别存储a和b的子序列,然后再用dp。
f[N][N]代表的是a的前i个字母和b的前j个字母的最长公共子序列的长度,这里用cnt1,cnt2来表示。
#include
#include
using namespace std;
const int N=1010;
int f[N][N];
string s1, s2;//要输入的两个序列
string str1[N], str2[N];//记录两个序列的所有子序列
int cnt1, cnt2;//相当于每个子序列的下标
int main()
{
cin >> s1 >> s2;
int d1 = s1.length(), d2 = s2.length();
for (int i = 0; i < d1;)
{
cnt1++;
if (s1[i] >= 'A' && s1[i] <= 'Z')//子序列首字母大写,后几位全小写
{
str1[cnt1] += s1[i++];
while (s1[i] >= 'a' && s1[i] <= 'z')
{
str1[cnt1] += s1[i++];
}
}
}
for (int i = 0; i < d2;)
{
cnt2++;
if (s2[i] >= 'A' && s2[i] <= 'Z')
{
str2[cnt2] += s2[i++];
while (s2[i] >= 'a' && s2[i] <= 'z')
{
str2[cnt2] += s2[i++];
}
}
}
for (int i = 1; i <= cnt1; i++)//遍历所有子序列
for (int j = 1; j <= cnt2; j++)
{
f[i][j] = max(f[i][j - 1], f[i - 1][j]);
if (str1[i] == str2[j]) f[i][j]=max(f[i][j], f[i - 1][j - 1] + 1);
}
cout << f[cnt1 ][cnt2 ] << endl;
return 0;
}
5.包子凑数
题解思路:这题一看就是完全背包问题的变种版,有几个物品,每个物品无限个,每个物品选任意个,能否凑到某个重量。
首先我们来了解一下什么是裴蜀定理:若a,b是整数,且gcd(a,b)=d,那么对于任意的整数x,y,ax+by都一定是d的倍数,特别地,一定存在整数x,y,使ax+by=d成立。
那么由裴蜀定理我们可知,若两个数x,y的gcd(x,y)为1,即 ax+by=1,ax+by一定是d的倍数,如果gcd不为一,那么就会存在数是x和y凑不出来的,
结论是如果所有的数的最大公约数不为1,就有不能凑出的数,并且小于10000,否则就有无限个(99和98是100内最大的互质的数,所以这个上界选择10000。
)
dp[i][j] 表示只取前i种笼子看看总和j是否能凑出来
#include
#include
#include
using namespace std;
typedef long long ll;
const int N = 10010;
int f[N];
int a[110];
int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
int main() {
int n;
cin >> n;
int d = 0;
for (int i = 1; i <= n; ++i) {
cin >> a[i];
d = gcd(d, a[i]);
}
if (d != 1)cout << "INF" << endl;
else {
f[0] = 1;
for (int i = 1; i <= n; ++i) {
for (int j = a[i]; j <= 10000; ++j) {
f[j]=max(f[j], f[j - a[i]]);//优化成1维
}
}
int res = 0;
for (int i = 0; i <= 10000; ++i)
if (!f[i])res++;
cout << res << endl;
}
return 0;
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)