模拟、枚举、贪心(一)

A-[NOIP2007]字符串的展开

简单模拟即可 

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int p1,p2,p3;
string s;
vector<char> ans;

void rep(char l,char r){//用来生成代替字符串的函数
    ans.push_back(l);
    if(r<=l){ans.push_back('-');}
    else if(r==l+1){}
    else {//l-r
        if(p1==1 && p3==1){
            for(char i=l+1;i<=r-1;i++)
                for(int k=0;k<p2;k++)
                    if(isalpha(l))ans.push_back(tolower(i));
                    else ans.push_back(i);
        }
        else if(p1==1){//逆序
            for(char i=r-1;i>=l+1;i--)
                for(int k=0;k<p2;k++)
                    if(isalpha(l))ans.push_back(tolower(i));
                    else ans.push_back(i);
        }
        else if(p1==2 && p3==1){
            for(char i=l+1;i<=r-1;i++)
                for(int k=0;k<p2;k++)
                    if(isalpha(l))ans.push_back(toupper(i));
                    else ans.push_back(i);
        }
        else if(p1==2){//逆序
            for(char i=r-1;i>=l+1;i--)
                for(int k=0;k<p2;k++)
                    if(isalpha(l))ans.push_back(toupper(i));
                    else ans.push_back(i);
        }
        else {
            for(int i=0;i<p2*(r-l-1);i++)
                ans.push_back('*');
        }
    }
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    cin>>p1>>p2>>p3>>s;
    int len=s.size();
    for(int i=0;i<len-1;i++){
        if(s[i+1]=='-'){
            if(( isdigit(s[i]) && isdigit(s[i+2]) ) ||
               ( isalpha(s[i]) && isalpha(s[i+2]) )){
                rep(s[i],s[i+2]);
                ++i;
            }
            else ans.push_back(s[i]);
        }
        else ans.push_back(s[i]);
    }
    ans.push_back(s[len-1]);
    for(int i=0;i<ans.size();i++)cout<<ans[i];
    return 0;
}

B-[NOIP2017]时间复杂度

2

 C-[NOIP2010]机器翻译

注意这里cnt不但可以记录个数,模m后表示字典中下一个要被删除的单词 

#include<bits/stdc++.h>
using namespace std;
int dict[110],pas[1010];
int main(){
    int m,n,cnt=0;
    cin>>m>>n;
    for(int i=0;i<n;i++)cin>>pas[i];
    for(int i=0;i<n;i++){
        bool check=false;
        if(cnt<m){
            for(int j=0;j<cnt;j++)
                if(dict[j]==pas[i]){check=1;break;}
            if(!check)dict[cnt++]=pas[i];
        }
        else {
            for(int j=0;j<m;j++)
                if(dict[j]==pas[i]){check=1;break;}
            if(!check)dict[cnt%m]=pas[i],cnt++;
        }
    }
    cout<<cnt;
}

或者使用find函数(代码量会减少一些) 

#include<bits/stdc++.h>
using namespace std;
int dict[110],pas[1010];
int main(){
    int m,n,cnt=0;
    cin>>m>>n;
    for(int i=0;i<n;i++){
        cin>>pas[i];
        if(cnt<m){
            if(find(dict,dict+cnt,pas[i])==dict+cnt)
                dict[cnt++]=pas[i];
        }
        else if(find(dict,dict+m,pas[i])==dict+m)
            dict[cnt%m]=pas[i],cnt++;
    }
    cout<<cnt;
}

提供一种时间复杂度低一些的解法:
注意最后一行是a[cnt-m-1]

#include<bits/stdc++.h>
using namespace std;
//vis用来判断数是否出现过,a用来记录放入的单词
int vis[1010],a[1010],m,n,x,cnt;
int main(){
    cin>>m>>n;
    for(int i=0;i<n;i++){
        cin>>x;
        if(vis[x])continue;
        a[cnt++]=x;
        vis[x]=1;
        if(cnt>=m) vis[a[cnt-m-1]]=0;
    }
    cout<<cnt;
}

D-四舍五入 

4

 E-安卓图案解锁

1.判断是否重复出现

2.判断是否跳过数字(将横竖斜都判断一遍)

3.将一些边的判断合并,如经过5的,然后(9,1)(3,7)配对判断

ps:详细看代码,结合图理解

#include<bits/stdc++.h>
using namespace std;
int main(){
    string s1;
    while(cin>>s1){
        vector<int> dict,s;
        bool check=1;
        for(int i=0;i<s1.size();i++)s.push_back(s1[i]-'0');
        dict.push_back(s[0]);
        for(int i=1;i<s.size();i++){
            for(int j=0;j<dict.size();j++){
                if(dict[j]==s[i]){check=false;break;}
            }
            if(s[i]+s[i-1]==10){
                if(find(dict.begin(),dict.end(),5)==dict.end()){
                    check=false;
                }
            }
            if(s[i]==9 || s[i]==1){
                if(s[i-1]==3 || s[i-1]==7)
                    if(find(dict.begin(),dict.end(),(s[i]+s[i-1])/2) == dict.end()){check=false;}
            }
            if(s[i]==7 || s[i]==3){
                if(s[i-1]==1 || s[i-1]==9)
                    if(find(dict.begin(),dict.end(),(s[i]+s[i-1])/2) == dict.end()){check=false;}
            }

            dict.push_back(s[i]);
        }
        if(check)printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}


F- 从后台研发到跑路

2

 G-回文数

1.注意前导0(00也算,0不算)(要出现前导0,有且仅有2种数字出现,并且非0的数字只有1个)

2.数量为奇数个的数不超过1个

#include<bits/stdc++.h>
using namespace std;
int a[10];
bool check1=1,check2=0,check=1;
vector<int> ans;
int main(){
    for(int i=0;i<10;i++)cin>>a[i];

    int cnt=0;//记录奇数个的数的个数
    for(int i=0;i<10;i++){if(a[i]&1) cnt++;}
    if(cnt>1)check=false;

    if(a[0]>=2){
        int sum=0;
        for(int i=0;i<10;i++){sum+=a[i];}
        if(a[0]+1==sum || a[0]==sum){
            printf("-1");
            return 0;
        }
    }
    if(check){
        int ji=-1;
        for(int i=0;i<10;i++)if(a[i]&1){ji=i;break;}
        for(int i=1;i<10;i++){
            if(a[i]>=2){
                ans.push_back(i);
                a[i]-=2;
                break;
            }
        }
        for(int i=0;i<10;i++){
            while(a[i]>=2)ans.push_back(i),a[i]-=2;
        }
        for(int i=0;i<ans.size();i++)cout<<ans[i];
        if(ji!=-1)cout<<ji;
        for(int i=ans.size()-1;i>=0;i--)cout<<ans[i];
    }
    else printf("-1");
    return 0;
}


 H-回文数

1

 I-[NOIP2016]玩具谜题

1

 J-[NOIP2015]神奇的幻方

 按题目所给条件模拟即可

#include<bits/stdc++.h>
using namespace std;
int n;
int a[40][40];
pair<int,int> pos;//记录上一个点的位置
int main(){
    cin>>n;
    a[1][(1+n)/2]=1;
    pos={1,(1+n)/2};
    for(int i=2;i<=n*n;i++){
        if(pos.first==1 && pos.second!=n){
            a[n][pos.second+1]=i;
            pos={n,pos.second+1};
        }
        else if(pos.second==n && pos.first!=1){
            a[pos.first-1][1]=i;
            pos={pos.first-1,1};
        }
        else if(pos.first==1 && pos.second==n){
            a[pos.first+1][pos.second]=i;
            pos={pos.first+1,pos.second};
        }
        else {
            if(a[pos.first-1][pos.second+1]==0){
                a[pos.first-1][pos.second+1]=i;
                pos={pos.first-1,pos.second+1};
            }
            else {
                a[pos.first+1][pos.second]=i;
                pos={pos.first+1,pos.second};
            }
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            cout<<a[i][j]<<' ';
        }
        cout<<endl;
    }
    return 0;
}


K-Tic-tac-toe

5

L-I love you 

dp比较难想到,想到之后挺简单的

#include<bits/stdc++.h>
using namespace std;
char ch;
int dp[8];//表示前i个字符在字符串中出现了dp[i]次
const int p=20010905;
int main(){
    string s;
    cin>>s;
    for(int i=0;i<s.size();i++){
        ch=tolower(s[i]);
        if(ch=='i')dp[0]++;
        if(ch=='l')dp[1]=(dp[1]+dp[0])%p;
        if(ch=='o')dp[2]=(dp[2]+dp[1])%p;
        if(ch=='v')dp[3]=(dp[3]+dp[2])%p;
        if(ch=='e')dp[4]=(dp[4]+dp[3])%p;
        if(ch=='y')dp[5]=(dp[5]+dp[4])%p;
        if(ch=='o')dp[6]=(dp[6]+dp[5])%p;
        if(ch=='u')dp[7]=(dp[7]+dp[6])%p;
    }
    cout<<dp[7]%p;
}

M-[NOIP2016]回文日期 

分解题目:

1.回文函数                2.找到下一个日期                3.闰年判断(当然可以和2合并) 

#include<bits/stdc++.h>
using namespace std;
const int run_mon[]={0,31,29,31,30,31,30,31,31,30,31,30,31};
const int mon[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
inline bool run(int year){
    if(year%4==0 &&(year%100!=0  || year%400==0)) return true;
    return false;
}

inline bool huiwen(int date){
    vector<int> s;
    while(date>0){
        s.push_back(date%10);
        date/=10;
    }
    for(int i=0;i<=(int)s.size()/2;i++){
        if(s[i]!=s[s.size()-1-i])return false;
    }
    return true;
}

inline int next_date(int date){
    int year,month,day;
    year=date/10000;
    month=date/100%100;
    day=date%100;
    if(run(year)){
        day++;
        if(day>run_mon[month]){day=1; month++;};
        if(month>12){month=1,year++;};
    }
    else {
        day++;
        if(day>mon[month]){day=1; month++;};
        if(month>12){month=1,year++;};
    }
    return year*10000+month*100+day;
}

int main(){
    int l,r,cnt=0;
    cin>>l>>r;
    if(huiwen(l))cnt++;
    while(next_date(l)<=r){
        l=next_date(l);
        if(huiwen(l))cnt++;
    }
    cout<<cnt;
    return 0;
}

 N-校门外的树

签到

#include<bits/stdc++.h>
using namespace std;
bool tree[10010];
int cnt,l,r,L,M;
int main(){
    cin>>L>>M;
    for(int i=0;i<M;i++){
        cin>>l>>r;
        for(int j=l;j<=r;j++)tree[j]=1;
    }
    for(int i=0;i<=L;i++){
        if(tree[i]==0)cnt++;
    }
    cout<<cnt;
}


O-值周

首先考虑算法可行性:考虑n的规模,时间复杂度要小于nlgn(可以用sort了) 

思路:排序后合并区间(见下图)

两个区间有交集的时候,合并成大区间;不然则开辟新区间,并将上一个区间的人赶走

#include<bits/stdc++.h>
#define ll long long
using namespace std;
vector< pair<int,int> > tree;
int cnt,L,M,l,r,len;
bool cmp(pair<int,int> a,pair<int,int>  b){
    return a.first<=b.first;
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    cin>>L>>M;
    int x,y;
    for(int j=0;j<M;j++){
        cin>>x>>y;
        tree.push_back({x,y});
    }
    sort(tree.begin(),tree.end(),cmp);
    l=tree[0].first,r=tree[0].second;
    for(int i=1;i<M;i++){
        if(tree[i].first>r+1){
            len+=r-l+1;
//          cout<<l<<" "<<r<<endl;
            l=tree[i].first;
            r=max(r,tree[i].second);
        }
        else {
            r=max(r,tree[i].second);
//          cout<<l<<" "<<r<<endl;
        }
    }
    len+=r-l+1;
    cout<<L+1-len;
}

P-货物种类

1

Q-储物点的距离

2

R-糖糖别胡说,我真的不是签到题

5

S-P1067 [NOIP2009 普及组] 多项式输出

下面提供两种思路:

1.按x的次数进行分类

2.对x的每项进行分类(符号、系数、x、幂数)

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n,a;
int main(){
    cin>>n;
    for(int i=n;i>=0;i--){
        cin>>a;
        if(!a)continue;
        if(i==n){
            if(a==1)cout<<"x^"<<i;
            else if(a==-1)cout<<"-x^"<<i;
            else cout<<a<<"x^"<<i;
        }
        else if(i==1){
            if(a==1)cout<<"+x";
            else if(a==-1)cout<<"-x";
            else if(a>0)cout<<"+"<<a<<"x";
            else if(a<0)cout<<a<<"x";
        }
        else if(i==0){
            if(a>0)cout<<"+"<<a;
            else cout<<a;
        }
        else{
            if(a==1)cout<<"+x^"<<i;
            else if(a==-1)cout<<"-x^"<<i;
            else if(a>0)cout<<"+"<<a<<"x^"<<i;
            else if(a<0)cout<<a<<"x^"<<i;
        }
    }
    return 0;
}
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n,a;
int main(){
    cin>>n;
    for(int i=n;i>=0;i--){
        cin>>a;
        if(!a)continue;
        //符号
        if(a<0)cout<<'-';
        else if(i!=n)cout<<'+';
        //系数
        if((abs(a)==1 && i==0) || abs(a)!=1)cout<<abs(a);
        //x及其幂数
        if(i!=0){
            if(i==1)cout<<'x';
            else cout<<"x^"<<i;
        }
    }
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值