19.8.12小白热身赛总结

2019爪哇小白校内热身赛

8.12 打的小白赛,题如期名,全是简单题和模板题,算是给后面的机考练练手,也算是了解了校内的水平,暑假因为其他事牵扯的关系,没有好好学习算法,没有好好完成计划,希望以后能够更加认真的学习算法。

A - A + B

//杭电1228  模拟
//题意给定例如three four + five six =
//输出A+B  
//由于刚开始习惯性看第一题,没有解决输入问题,打了一遍代码案例过不了就跳题
//过后一天才补回来
#include<iostream>
#include<string>
#include<map>
using namespace std;
int main()
{
    map<string ,int>q;
    q["one"]=1;q["two"]=2;q["three"]=3;q["four"]=4;q["five"]=5;
    q["six"]=6;q["seven"]=7;q["eight"]=8;q["nine"]=9;q["ten"]=10;
    string s;
    while(1)
    {
        int a=0,b=0;
        while(cin>>s&&s!="=")
        {
            if(s!="+") a=a*10+q[s];
            else b=a,a=0;
        }
        if(a==0&&b==0) break;
        else cout<<a+b<<endl;
    }
    return 0;
}

B - 3n + 1?

//POJ 1207  模拟
//若n为偶数,则n=n/2;否则n=n*3+1
//给定一个区间[l,r]求最多的操作数
//坑点:l r没有一定的大小关系 最后答案的输出必须原区间
#include<iostream>
using namespace std;
const int manx=1e4+5;
int a[manx],b[manx];
int main()
{
    int l,r;
    std::ios::sync_with_stdio(false);
    while(cin>>l>>r)
    {
        int ans,res,maxx=-1;
        for(int i=min(l,r);i<=max(l,r);i++){
            res=i,ans=1;
            if(res==0) ans=0;
            while(res>1)
            {
                if(res%2==1) res=res*3+1;
                else res/=2;
                ans++;
            }
            if(ans>maxx) maxx=ans;
        }
        cout<<l<<" "<<r<<" "<<maxx<<endl;
    }
    return 0;
}

最爱字符串

//HihoCoder - 1485  尺取法/滑动窗口/双指针
//求字符串中含有2个"h" 1个"i" 1个"o" 的最短子串
//没听过尺取法/滑动窗口,本来想用双指针做,后面时间不够就没有写,赛后补了回来
#include<iostream>
#include<string>
#include<map>
using namespace std;
const int manx=1e5+5;
struct node
{
    int pos; //记录位置
    char c;  //记录所在位置的字符
}a[manx];
int main()
{
    string s;
    cin>>s;
    map<char ,int >q;
    int ans=manx,p=0;
    for(int i=0;i<s.size();i++)
        if(s[i]=='h'||s[i]=='o'||s[i]=='i')
        {
            p++;
            a[p].c=s[i];
            a[p].pos=i;
        }
    int head=1;
    for(int i=1;i<=p;i++)
    {
        if(i<=4) q[ a[i].c ]++;
        else {
            q[ a[head].c] --;
            q[ a[i].c ] ++;
            head++;
        }
        if(q['h']==2 && q['o']==1 && q['i']==1)
            ans=min(ans,a[i].pos-a[head].pos+1);
    }
    if(ans!=manx) cout<<ans<<endl;
    else cout<<-1;
    return 0;
}

D - 序列和

// hdu 1231 dp经典
//比子序列问题多了求初始位置和终止位置 也就多了一个比较过程
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int manx=1e4+5;
int a[manx],dp[manx];
int main()
{
    int n;
    while(cin>>n&&n)
    {
        for(int i=1;i<=n;i++)
            cin>>a[i];
        int l=0,r=0,ll,rr,ans=-1;
        for(int i=1;i<=n;i++)
        {
            if(i==1) ans=dp[1]=a[1],ll=i,rr=i;
            else dp[i]=max(dp[i-1]+a[i],a[i]);
            if(dp[i]==a[i]) l=i,r=i;
            else r=i;
            if(dp[i]>ans) ans=dp[i],ll=l,rr=r;
        }
        if(ans<0) ans=0,ll=1,rr=n;
        cout<<ans<<" "<<a[ll]<<" "<<a[rr]<<endl;
    }
    return 0;
}

E - 迷宫

//poj 3984
//伪AC代码 本题考查广搜?深搜? 输出最短路径数并输出路径
//由于本人喜爱深搜但又不会广搜,所以用深搜大法师水了一发
//注意dx和dy数组的设置,一定要先往右边和先往下边走,这样好占数据的便宜,数据一弱就过了
//等学完广搜再补回来
#include<iostream>
#include<vector>
using namespace std;
int a[6][6],check[6][6],dx[4]={0,1,-1,0},dy[4]={1,0,0,-1};
int bestValue=25;
vector<int> path;
vector<int> tempPath;
void DFS(int v,int p,int value){
    tempPath.push_back(v);
    tempPath.push_back(p);
    if(v == 4&& p==4 ){
        if(value < bestValue){
            bestValue = value;
            path = tempPath;
        }
        return ;
    }
    for(int i=0;i<4;i++){
        if( a[v+dx[i]][p+dy[i]] && !check[v+dx[i]][p+dy[i]])
        {
            check[v+dx[i]][p+dy[i]]=1;
            DFS(v+dx[i],p+dy[i],value++);
            check[v+dx[i]][p+dy[i]]=0;
        }
    }
    tempPath.pop_back();
    tempPath.pop_back();
}
int main()
{
    int m;
    for(int i=0;i<5;i++)
        for(int j=0;j<5;j++)
        {
            cin>>m;
            if(m) a[i][j]=0;
            else a[i][j]=1;
        }
    DFS(0,0,0);
    for(int i=0;i<path.size();i++)
    {
        if(i%2==0) cout<<"("<<path[i]<<", ";
        else cout<<path[i]<<")"<<endl;
    }
    return 0;
}

F - 布阵

//hdu 1166
//线段树模板题 考察区间查询和单点修改
//模板贴上去打上return 0  1分钟AC一气呵成
#include<iostream> //线段树模板
#include<cstdio>
using namespace std;
typedef long long ll;
const int manx=100010;

ll n,p,a,b,m,x,y,ans;
ll aa[manx+5];

struct node
{
    ll l,r,w,f;
}tree[4*manx];

inline void build(ll k,ll l,ll r)//建树
{
    tree[k].l=l,tree[k].r=r;
    if(tree[k].l==tree[k].r)
    {
        tree[k].w=aa[l];
        return;
    }
    int m=(l+r)/2;
    build(k*2,l,m);
    build(k*2+1,m+1,r);
    tree[k].w=tree[k*2].w+tree[k*2+1].w;
}
inline void down(ll k)//标记下传
{
    tree[k*2].f+=tree[k].f;
    tree[k*2+1].f+=tree[k].f;
    tree[k*2].w+=tree[k].f*(tree[k*2].r-tree[k*2].l+1);
    tree[k*2+1].w+=tree[k].f*(tree[k*2+1].r-tree[k*2+1].l+1);
    tree[k].f=0;
}
inline void ask_point(ll k)//单点查询
{
    if(tree[k].l==tree[k].r)
    {
        ans=tree[k].w;
        return ;
    }
    if(tree[k].f) down(k);
    int m=(tree[k].l+tree[k].r)/2;
    if(x<=m) ask_point(k*2);
    else ask_point(k*2+1);
}
inline void change_point(ll k)//单点修改
{
    if(tree[k].l==tree[k].r)
    {
        tree[k].w+=y;
        return;
    }
    if(tree[k].f) down(k);
    int m=(tree[k].l+tree[k].r)/2;
    if(x<=m) change_point(k*2);
    else change_point(k*2+1);
    tree[k].w=tree[k*2].w+tree[k*2+1].w;
}
inline void ask_interval(ll k)//区间查询
{
    if(tree[k].l>=a&&tree[k].r<=b)
    {
        ans+=tree[k].w;
        return;
    }
    if(tree[k].f) down(k);
    int m=(tree[k].l+tree[k].r)/2;
    if(a<=m) ask_interval(k*2);
    if(b>m) ask_interval(k*2+1);
}
inline void change_interval(ll k)//区间修改
{
    if(tree[k].l>=a&&tree[k].r<=b)
    {
        tree[k].w+=(tree[k].r-tree[k].l+1)*y;
        tree[k].f+=y;
        return;
    }
    if(tree[k].f) down(k);
    int m=(tree[k].l+tree[k].r)/2;
    if(a<=m) change_interval(k*2);
    if(b>m) change_interval(k*2+1);
    tree[k].w=tree[k*2].w+tree[k*2+1].w;
}
int main()
{
    int t;
    cin>>t;
    for(int p=1;p<=t;p++)
    {
        cout<<"Case "<<p<<":"<<endl;
        cin>>n;
        for(int i=1;i<=n;i++)
            cin>>aa[i];
        build(1,1,n);//建树
        string s;
        while(cin>>s){
            ans=0;
            if(s[0]=='Q')
            {
                scanf("%lld%lld",&a,&b);
                ask_interval(1);
                printf("%lld\n",ans);
            }
            else if(s[0]=='S')
            {
                scanf("%lld%lld",&x,&y);
                y*=-1;
                change_point(1);
            }
            else if(s[0]=='A')
            {
                scanf("%lld%lld",&x,&y);
                change_point(1);
            }
            else break;
        }
    }
    return 0;
}

G - 鸡你太美

//poj 1611
//并查集 模板题 
//有一群人 分成几个小团体 只要有人病患的团体全部病患 一开始只有0患病
//查找0是爸爸的个数
#include<iostream>
using namespace std;
const int manx=3e4+5;
int a[manx];
int find(int x)
{
    if(a[x]==x) return x;
    else return a[x]=find(a[x]);
}
int main()
{
    int n,m,p,x,y,ans=0;
    std::ios::sync_with_stdio(false);
    while(cin>>n>>m&& (m||n))
    {
        for(int i=0;i<n;i++)
            a[i]=i;
        while(m--)
        {
            cin>>p>>x;
            for(int i=1;i<p;i++)
            {
                cin>>y;
                a[find(x)]=find(y);
                x=y;
            }
        }
        for(int i=0;i<n;i++)
            if(find(a[i])==find(0))
                ans++;
        cout<<ans<<endl;
        ans=0;
    }
}

J - 数论大定理

// hud  6441
//费马大定理
//a^n+b^n=c^n 当n>2时无解 350年来的智商接力
//其中n=2时 有:
//若a = 2 * k + 1,则 c = k ^ 2 + ( k + 1 ) ^ 2 ,b = c - 1
//若a = 2 * k + 2,则 c = 1 + (k + 1) ^ 2 , b = c - 2 
#include <cstdio>
#define ll long long
ll T, a, b, c, n;
int main(){
    scanf("%lld", &T);
    while(T--){
        scanf("%lld %lld", &n, &a);
        if(n == 2){
            if(a%2){
                ll t = (a-1)/2;
                c = t*t+(t+1)*(t+1);
                b = c-1;
            }
            else{
                ll t = (a+2)/2;
                c = 1+(t-1)*(t-1);
                b = c-2;
            }
            printf("%lld %lld\n", b, c);
        }
        else if( n == 1){
            printf("1 %lld\n", a+1);
        }
        else{
            printf("-1 -1\n");
        }
    }
}

K - 有向图

// hdu 1269  
// 强连通图的判断 
// 这里我是用两个并查集 一个从1到n 一个从n到1 进行判定连通性
#include<iostream>
#include<cmath>
#include<string>
#include<cstdio>
using namespace std;
const int manx=1e4+5;
int a[4][manx];
int n,m;
int find(int x,int i)
{
    return x==a[i][x]?x:a[i][x]=find(a[i][x],i);
}
void fun(int x,int y)
{
    if(x!=n){
        int xx=find(x,1);
        int yy=find(y,1);
        if(xx!=yy) a[1][x]=y; //把y放在x的后面
    }
    if(y!=n)
    {
        int xx=find(x,2);
        int yy=find(y,2);
        if(xx!=yy) a[2][y]=x; //把x放在y的后面
    }
}
int main()
{
    while(scanf("%d %d",&n,&m)!=EOF&&(m||n))
    {
        int b,c,flag=1;
        for(int i=1;i<=2;i++)
            for(int j=1;j<=n;j++)
                a[i][j]=j;
        for(int i=1;i<=m;i++)
            scanf("%d",&b),scanf("%d",&c),fun(b,c);
        for(int i=1;i<=n;i++)
        {
            if(find(i,1)!=n||find(i,2)!=n)
            {
                flag=0;
                break;
            }
        }
        if(flag) printf("Yes\n");
        else   printf("No\n");
    }
    return 0;
}

L - 钱币兑换

//hdu1284   dp
//完全背包问题 没啥好说
#include<iostream>
using namespace std;
const int manx=32768;
long long dp[32768];
int main()
{
    dp[0]=1;
    for(int i=1;i<=3;i++)
        for(int j=1;j<=manx;j++)
            dp[j]+=dp[j-i];
    int n;
    std::ios::sync_with_stdio(false);
    while(cin>>n)
    {
        cout<<dp[n]<<endl;
    }
    return 0;
}

M - 又是A+B

//hdu 2524 思维+模拟
//求矩形个数
//行列分割 可以发现跟小学时代求三角形个数一样
//都是从1+2+……+n
//可以得到n行m列的公式为:n*(n+1)/2*m*(m+1)/2 
#include<iostream>
#include<map>
using namespace std;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int a,b;
        cin>>a>>b;
        cout<<a*(a+1)/2*b*(b+1)/2<<endl;
    }
    return 0;
}

N - 素数

//hdu 1262  模拟+素数
//对于每个偶数,输出两个彼此最接近的素数,其和等于该偶数
//打完素数表后枚举就可以了
#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
const int manx=1e4+5;
bool prime[manx];
void make_prime()
{
    memset(prime,true,sizeof(prime));
    prime[0]=prime[1]=false;
    int t=sqrt(manx);
    for(int i=2;i<=t;i++)
    {
        if(prime[i])
            for(int j=2*i;j<manx;j+=i)
            {
                prime[j]=false;
            }
    }
    return;
}
int main()
{
    make_prime();
    int n;
    while(cin>>n)
    {
        for(int i=n/2;i>0;i--)
            if(prime[i]&&prime[n-i]){
                cout<<i<<" "<<n-i<<endl;
                break;
            }
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值