基础练习(2)
1.
很容易看出题目必须是一个等差数列。
考虑固定两个数,就可以求出整个数列,记录不相等的数即可。然后记录需要的最小次数。
因为直接求公差会出现误差,所以考虑直接
对这个柿子边下形就好了。
/*
发现有种情况没有讨论
可能不是这个等差数列的数也是不需要改动的。
0,2,4,100 ,10只需要1次输出了2
那如何确定一个等差数列只需要固定两个数,然后就可以算出整个数列是什么了
*/
void slove(){
cin>>n;
fel(i,1,n) cin>>a[i];
int ans=n-1;
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
int c=a[j]-a[i];
int d=j-i;
int cnt=0;
for(int k=1;k<=n;k++){
int u=a[k]-a[i];
int v=k-i;
if(c*v!=u*d) cnt++;
}
ans=min(ans,cnt);
}
}
cout<<ans<<endl;
}
2.
首先考虑如果能不能测试这一场,如果后面也有一场不能测试,那我肯定考虑在后面那一场再降智。这样才会一直保持较高的智商。才能取走更多东西。那如何实现先取后面的呢?考虑从后面取。这样才会优先取到后面的。
void slove(){
cin>>n>>q;
fel(i,1,n) cin>>a[i];
int cnt=0;
string s="";
feh(i,n,1){
if(cnt<a[i]&&cnt<q){
cnt++;
s+="1";
}
else if(cnt>=a[i]) s+='1';
else s+="0";
}
reverse(s.begin(),s.end());
cout<<s<<endl;
}
3.
感觉这种题目套路都差不多,就是考虑复制的时候我当前字符串在前面什么位置,然后考虑直递归解决即可。
这个题目我就直接考虑保存每一次复制之后字符串的长度和复制上一次字符串的区间。然后通过递归就可以知道当前位置的字符在上一次字符串里面是什么位置。
void slove(){
cin>>n>>c>>q;
cin>>s;
sum[0]=n;
for(int i=1;i<=c;i++){
cin>>l[i]>>r[i];
sum[i]=sum[i-1]+r[i]-l[i]+1;
}
for(int i=1,x;i<=q;i++){
cin>>x;
for(int j=c;j>=1;j--){
if(x<=sum[j]&&x>sum[j-1]){
x=l[j]+x-sum[j-1]-1;
}
}
cout<<s[x-1]<<endl;
}
}
4.
就是对前面的字符尽量选择大的,然后如何判断这个字符可不可以选呢?
就是我后面的字符没有他,或者后面有25给字母绕个圈于是他就可以接在我的头上。
const int N=500;
int n;
string s;
int q[N],h[N],vis[N],cnt,flag;
void dfs(int now,int pre){
if(now==-1) return;
cnt++;
if(now==pre) flag=1;
dfs(h[now],pre);
}
bool check(char pre,char ne){
if(pre!=ne&&vis[pre]==0){//pre此时还没做过前驱,所以只要搜他在ne的后面没即可。
//两种可能一种是这个字符还没用过,另外一种是是ne和pre之间隔24个字母首位相接
cnt=0,flag=0;
dfs(h[ne],pre);
if(flag==0||cnt==25){
return true;
}
}
return false;
}
void slove(){
cin >> n;
cin >> s;
s = " " + s;
fel(i,0,200) vis[i]=0,q[i]=-1,h[i]=-1;
string ans="";
fel(i,1,n){
if(q[s[i]]!=-1){
ans+=q[s[i]];
continue;
}
for(char j='a';j<='z';j++){
if(check(j,s[i])){
q[s[i]]=j;
h[j]=s[i];