C - String Game
传送门
题意: 给定一串母串和一串子串,在母串中匹配子串,不需要是连续的子串,只要出现顺序一样即可
思路: dp题。开二维,第一位存子串中已经匹配到的数位,第二位存母串当前遍历到的数位。然后推出动态转移方程
公共子序列,公共子串的题型有很多,也多涉及动态规划,需要多练习总结。
#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
const int maxn=5005;
int dp[maxn][maxn];
//第一位存子串中已经匹配到的数位,第二位存母串当前遍历到的数位
int main()
{
string s1,s2;
while(cin>>s1>>s2)
{
int len1=s1.length(),len2=s2.length();
for(int i=0;i<=len1;i++) dp[0][i]=1;
for(int j=1;j<=len2;j++) //初始化
{
for(int i=1;i<=len1;i++)
dp[j][i]=0;
}
for(int i=1;i<=len2;i++)
{
for(int j=1;j<=len1;j++)
{//遍历s1依次校对来找s2的各个字符
//配对成功则转移并累加 否则照搬不变
if(s1[j-1]==s2[i-1])
dp[i][j]=(dp[i][j-1]+dp[i-1][j-1])%mod;
else dp[i][j]=dp[i][j-1]%mod;
}
}
cout<<dp[len2][len1]<<endl;
}
return 0;
}
E - Shorten the Array
传送门
题意: 可任取两个非零元素a[i]、a[i+1]进行合并消除,新元素a[i]=a[i]%a[i+1] || a[i+1]%a[i],求消完后的数组最短长度
思路: 思维题。①若全都一样,只能两两消除,最后剩
n
+
1
2
\frac{n+1}{2}
2n+1 个 ②若存在最小值,可以通过 “最小值”%“大”=“最小值” 来操作,最后全都消成最小值,转化为①的情况。那么只要求最小值个数minnum即可 ③若满足 “大”%“最小值”<“最小值” 且 !=0 那就必定可以消成只剩一个数,所以进行完②后要对特殊情况特判。
t了一发,把求最小值的方法从“遍历比较”—>“利用min_element求容器最小值”就过了,时间直接缩一半。–>好东西
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int inf=0x3f3f3f3f;
const int maxn=1e6+5;
int a[maxn],n,minn;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int minnum=0;
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
minn=*min_element(a+1,a+1+n); //寻找最小值
for(int i=1;i<=n;i++) //统计最小值个数
if(a[i]==minn) minnum++;
for(int i=1;i<=n;i++) //更新最小值
{
int x=a[i]%minn;
if(x!=0&&x<minn)
{
minnum=1;
break;
}
}
minnum=(minnum+1)/2;
printf("%d\n",minnum);
}
return 0;
}