A签到题
问题描述:
东东在玩游戏“Game23”。
在一开始他有一个数字n,他的目标是把它转换成m,在每一步操作中,他可以将n乘以2或乘以3,他可以进行任意次操作。输出将n转换成m的操作次数,如果转换不了输出-1。
Input
输入的唯一一行包括两个整数n和m(1<=n<=m<=5*10^8).
Output
输出从n转换到m的操作次数,否则输出-1.
Simple Input 1
120 51840
Simple Output 1
7
Simple Input 2
42 42
Simple Output 2
0
Simple Input 3
48 72
Simple Output 3
-1
思路:
先让n尽可能的3在被m求余为0的情况下,然后尽可能的2(同3)(要求最少,所以先3在*2),最后n和m相等就可以转换成功,输出结果,如不相等则不能转换成功输出-1
#include<iostream>
using namespace std;
void cs()
{
long long int n,m,result=0;
cin>>n>>m;
while(m%(n*3)==0&&m>=(n*3))
{
n=n*3;
result++;
}
while(m%(n*2)==0&&m>=(n*2))
{
n=n*2;
result++;
}
if(m==n)
{
cout<<result<<endl;
}else
{
cout<<"-1"<<endl;
}
}
int main()
{
cs();
return 0;
}
B:LIS&LCS
问题描述:
东东有两个序列A和B。
他想要知道序列A的LIS和序列AB的LCS的长度。
注意,LIS为严格递增的,即a1<a2<…<ak(ai<=1,000,000,000)。
Input
第一行两个数n,m(1<=n<=5,000,1<=m<=5,000)
第二行n个数,表示序列A
第三行m个数,表示序列B
Output
输出一行数据ans1和ans2,分别代表序列A的LIS和序列AB的LCS的长度
Simple Input
5 5
1 3 2 5 4
2 4 3 1 5
Simple Output
3 2
思路:
最长上升子序列:
这个比较简单就不仔细介绍了
公共最长子序列:
用f[i][j]来代表A1,…Ai和B1,…Bj的LCS
列出状态转移方程:
若Ai==Bj,则f[i][j]=f[i-1][j-1]+1;
若Ai!=Bj,则f[i][j]=max(f[i-1][j],f[i][j-1]);
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
int n,m;
int a[5010],b[5010],f[5010][5010];
void LIS()
{
int c=1,ans[5010];
memset(ans,0,sizeof(ans));
ans[1]=a[1];
for(int i=2;i<=n;i++)
{
if(a[i]>ans[c])
{
ans[++c]=a[i];
}else
{
int d=lower_bound(ans+1,ans+c+1,a[i])-ans;
ans[d]=a[i];
}
}
cout<<c<<" ";
}
void LCS()
{
f[1][0]=f[0][1]=f[0][0]=0;
for(int i=1;i<=n;i++)
{
for(int i1=1;i1<=m;i1++)
{
if(a[i]==b[i1])
{
f[i][i1]=f[i-1][i1-1]+1;
}else
{
f[i][i1]=max(f[i-1][i1],f[i][i1-1]);
}
}
}
cout<<f[n][m];
}
void cs()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
for(int i=1;i<=m;i++)
{
cin>>b[i];
}
LIS();
LCS();
}
int main(int argc, char const *argv[])
{
cs();
return 0;
}
C - 拿数问题 II
问题描述:
YJQ 上完第10周的程序设计思维与实践后,想到一个绝妙的主意,他对拿数问题做了一点小修改,使得这道题变成了 拿数问题 II。
给一个序列,里边有 n 个数,每一步能拿走一个数,比如拿第 i 个数, Ai = x,得到相应的分数 x,但拿掉这个 Ai 后,x+1 和 x-1 (如果有 Aj = x+1 或 Aj = x-1 存在) 就会变得不可拿(但是有 Aj = x 的话可以继续拿这个 x)。求最大分数。
本题和课上讲的有些许不一样,但是核心是一样,需要你自己思考。
Input
第一行包含一个整数 n (1 ≤ n ≤ 105),表示数字里的元素的个数
第二行包含n个整数a1, a2, ..., an (1 ≤ ai ≤ 105)
Output
输出一个整数:n你能得到最大分值。
Example
Input
2
1 2
Output
2
Input
3
1 2 3
Output
4
Input
9
1 2 1 3 2 2 2 2 3
Output
10
Hint
对于第三个样例:先选任何一个值为2的元素,最后数组内剩下4个2。然后4次选择2,最终得到10分。
思路:
这道题依然是dp问题;
dp[i] = max(dp[i-1],dp[i-2]+ans[i]*i)。
ans[i]*i为获得的分值
必须要用long long 否则会出错
#include<iostream>
#include<algorithm>
#include<string.h>
#include<cmath>
using namespace std;
long long int n;
long long int num[100010],ans[100010],vis[100010];
void cs()
{
memset(ans,0,sizeof(ans));
long long int result=0;
cin>>n;
for(long long int i=0;i<n;i++)
{
cin>>num[i];
ans[num[i]]++;
}
sort(num,num+n);
for(long long int i=num[0];i<=num[n-1];i++)
{
vis[i]=max(vis[i-1],vis[i-2]+i*ans[i]);
result=max(result,vis[i]);
}
cout<<result<<endl;
}
int main()
{
cs();
}