A:水过
B:模拟题水过
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <math.h>
#define bug cout <<"bug" <<endl
using namespace std;
typedef long long ll;
char s1[500],s2[500];
int cnts[50];
int cntt[50];
int check(){
int i,j,n,m,dp[1000],book[1000],s;
n=strlen(s1);
m=strlen(s2);
for(i=1;i<=n;i++)
{
s=0;
for(j=1;j<=m;j++)
{
if(s1[i-1]==s2[j-1])
dp[j]=book[j-1]+1;
else if(dp[j-1]>book[j])
dp[j]=dp[j-1];
else
dp[j]=book[j];
book[j-1]=s;
s=dp[j];
}
book[m]=s;
}
return dp[m];
}
int main(void){
scanf("%s%s",s1,s2);
int len1=strlen(s1),len2=strlen(s2);
for(int i=0;i<len1;i++) cnts[s1[i]-'a'+1]++;
for(int i=0;i<len2;i++) cntt[s2[i]-'a'+1]++;
for(int i=1;i<=26;i++){
if(cntt[i]>cnts[i]){
//cout <<"i="<<i<<endl;
//cout <<cntt[i] << " "<<cnts[i];
printf("need tree\n");
return 0;
}
}
bool flag1=false,flag2=false;
if(len1>len2) flag1=true;
int ans=check();
if(ans!=len2) flag2=true;
if(flag1==true && flag2==true) cout <<"both"<<endl;
else if(flag1==true && flag2==false) cout <<"automaton"<<endl;
else if(flag1==false && flag2==true) cout <<"array"<<endl;
return 0;
}
C:
题意:给定n个连续栅栏宽度1m,高度各不相同,现在有一把刷子宽度1m,只能横刷或者竖刷,遇到有断裂的地方就不能继续刷。 问,至少刷几次才能刷玩。
思路:
1.n一定是一个合理答案,即全部竖刷
2.为了求更优解,我们尝试着使用部分横刷去弥补竖着刷带来的不足。
3.如何确定横着刷带来的最大效益呢? 假设当前hmin为高度最小的栅栏,那么我们把所有的点都减去hmin,那么剩下来的部分又会出现下一个hmin,以0作为区间的划分标准,答案最小值又是当前hmin和当前的栅栏个数Xi。如此递归下去,直至当l==r时,返回1.
#include <bits/stdc++.h>
#define bug cout <<"bug" <<endl
using namespace std;
typedef long long ll;
int n;
int a[5005];
int dfs(int l,int r){
int mmin=a[l];
int ans1=r-l+1;
for(int i=l+1;i<=r;i++)
if(a[i]<mmin) mmin=a[i];
int ans=mmin;
for(int i=l;i<=r;i++) a[i]-=mmin;
for(int i=l;i<=r;i++){
if(a[i]){
int nl=i;
int nr=i;
while(nr<=n&&a[nr]) nr++;
nr--;
ans+=dfs(nl,nr);
}
}
return min(ans1,ans);
}
int main(void){
cin >> n;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
printf("%d\n",dfs(1,n));
}
D
题意:n*m的矩阵a[i][j]=i*j 问第k大为多少
思路: 注意题意!第k大的定义是从小到大非递减序列的第k个。 那么二分答案即可,利用在n*m的矩阵中有性质:比x小的数cnt= x/i个 (i属于1~n)
二分,如果cnt >=k 那么 记录ans=mid, r=mid-1; else , l=mid+1
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <math.h>
#define bug cout <<"bug" <<endl
using namespace std;
typedef long long ll;
ll n,m,k;
ll check(ll x){
ll cnt=0;
for(int i=1;i<=n;i++) cnt+=min(x/i,m);
return cnt >= k;
}
int main(void){
cin >> n >>m >>k;
ll l=1,r=n*m;
ll ans;
while(l<=r){
ll mid=(l+r)/2;
if(check(mid)) ans=mid,r=mid-1;
else l=mid+1;
}
cout << ans << endl;
}
E
题意:把x进行质因数分解k次,对其所有质因数再分解质因数直至1或者k==0。
思路:DFS ,如果n==1或者k==0 return ; 这里有一个性质:x的质因数 的 质因数 仍在 x的质因数范围内。因为x是这个数的整数倍。
#include <bits/stdc++.h>
#define bug cout <<"bug"<<endl
using namespace std;
typedef long long ll;
const int N=1e7+5;
ll vec[N];
ll cnt=0,cur=0;
ll len;
void DFS(ll n,ll k){
if(cnt>=1e5) return ;
if(k==0 || n==1){
printf("%lld ",n);
cnt++;
return ;
}
//cout <<"len="<<len<<endl;
for(register ll i=0;i<len && n>=vec[i];i++)
if(n%vec[i]==0) DFS(vec[i],k-1);
}
int main(void){
ll x,k;
scanf("%lld%lld",&x,&k);
for(register ll i=1;i*i<=x;i++){
if(x%i==0){
vec[cur++]=i;
if(x/i!=i) vec[cur++]=x/i;
}
}
sort(vec,vec+cur);
len=cur;DFS(x,k);
//cout <<"cnt="<<cnt<<endl;
}