wxy 3.3 牛客练习赛58重现
v>
wxy 3.3 牛客练习赛58重现
4756
C
没有办法都枚举的话,就枚举一维剩下一维可以凑,考虑用二进制枚举取哪些行,然后用剩下的列数中
的最大的前几个凑足k。复杂度最差2^15 * 15* 15。
D
棋盘DP【DP真是思维的体操啊,一看就会,一做就废,QAQ】
如果右边没有障碍,那么就可以往右走;如果右边有障碍,下边没有障碍,那么可以往下走;如果下边
有障碍,那么会往左走,但是因为往左走了之后右边空出来了,又可以往右走就会造成循环;如果往上
走那么又回去了,只有往下或者往右才是有效的。然后考虑,如果当前是没有障碍物的如果右边可以移
动那么就有两个选择,往右边走,代价会不变化取小的那个;往下走,代价+1.如果右边有障碍物,那
么就往下走,代价不会变化取小的那个。如果最后DP[n] [m]不是INF,说明可以到达,否则则说明不能
到达
# include <bits/stdc++.h>
using namespace std;
const int MAXN=1e3+100;
const int INF=1e9;
char s[MAXN][MAXN];
int dp[MAXN][MAXN];
int main()
{
int n,m; scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++) dp[i][j]=INF;
for(int i=1;i<=n;i++){
scanf("%s",s[i]+1);
}
dp[1][1]=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(s[i][j]=='0'){
if(j<m&&s[i][j+1]=='0'){
dp[i][j+1]=min(dp[i][j+1],dp[i][j]);
if(i<n&&s[i+1][j]=='0') dp[i+1][j]=min(dp[i+1][j],dp[i]
[j]+1);
}else{
if(i<n&&s[i+1][j]=='0') dp[i+1][j]=min(dp[i+1][j],dp[i][j]);
}
}
}
}
if(dp[n][m]==INF){
printf("-1\n");
}else printf("%d\n",dp[n][m]);
return 0;
}E
考虑求一个数的因子需要sqrt(x)的复杂度,把给定的数的因子都求出来,分别在vector里方每个因子会
出现的位置。对于询问,根号遍历x的因子,在对应的数组中low_b log查找,判断下标是否在区间内。
复杂度 n*sqrt(n) *log
# include <bits/stdc++.h>
using namespace std;
const int MAXN=1e5+100;
vector<int> v[MAXN];
int a[MAXN];
void fac(int aa,int id)
{
for(int i=1;i*i<=aa;i++){
if(aa%i==0){
v[i].push_back(id);
if(aa/i!=i) v[aa/i].push_back(id);
}
}
}
int solve(int l,int r,int x)
{
int p=lower_bound(v[x].begin(),v[x].end(),l)-v[x].begin();
if(p==v[x].size()) return 0;
if(v[x][p]>=l&&v[x][p]<=r) return 1;
else return 0;
}
int main()
{
int n,q; scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
fac(a[i],i);
}
while(q--){
int ans=0;
int l,r,x; scanf("%d%d%d",&l,&r,&x);
for(int i=1;i*i<=x;i++){
if(x%i==0){
if(solve(l,r,i)) ans=max(ans,i);
if(x/i!=i){
if(solve(l,r,x/i)) ans=max(ans,x/i);
}
}
}
printf("%d\n",ans);
}
return 0;
}
向wjmzbmr学习,acm本就是逆天而行。
浙公网安备 33010602011771号