笔记2

有一部分本人所写,一部分借鉴其他博客,侵删。

Fibsieve`s Fantabulous Birthday

 LightOJ - 1008 

#include<bits/stdc++.h>

using namespace std;

#define ll long long

ll res;ll ress;

int main()

{

    ios::sync_with_stdio(false);

    int n;

    cin>>n;int ccase=0;

    while(n--)

    {

        cin>>ress;

        res=sqrt(ress);

        cout<<"Case "<<++ccase<<": ";

        if(res*res==ress&&res%2==1)

        {

            cout<<1<<" "<<res<<endl;

            continue;

 

        }

        if(res*res==ress&&res%2==0)

        {

            cout<<res<<" "<<1<<endl;

            continue;

 

        }

         if(res%2==0)

        {

            if(res*res+res+1>=ress)

            {

                cout<<res+1<<" "<<ress-res*res<<endl;

            }

            else

            {

                cout<<(res+1)*(res+1)-ress+1<<" "<<res+1<<endl;

            }

        }

        else

        {

            if(res*res+res+1>=ress)

            {

                cout<<ress-res*res<<" "<<res+1<<endl;

            }

            else

            {

                cout<<res+1<<" "<<(res+1)*(res+1)-ress+1<<endl;

            }

        }

 

    }

    return 0;

}

看来这道题目比较简单了,自己做的。

要分偶数和奇数,然后要再分情况。同时要注意格式。至于为什么在一个特定的点是平方数,是因为,相邻是等差数列(由于特征),那么通项公式一定是二次的,通过前几项确定了平方数。

Hdu5578

看来签到题简单也是挺正常的了。

#include<bits/stdc++.h>

using namespace std;

char a[1010];

int main()

{

    int t;

    cin>>t;int ccase=0;

    while(t--)

    {

        cin>>a;

        cout<<"Case #"<<++ccase<<": ";

        int res=2222;

 

        for(int i=0;i<strlen(a);i++)

        {

            for(int j=i+1;j<strlen(a);j++)

            {

                if(a[i]==a[j])

                {

                    res=min(res,j-i);

                    break;

 

                }

 

            }

        }

        if(res==2222) cout<<-1<<endl;

        else cout<<res<<endl;

    }

    return 0;

}

Hdu5583

首先,是中间一定会变小,要学会尽量化简。其次是复杂度的分析。接下来就是熟练地写加上准确度。

 

 

 

 

 

Cf65B

要学会使用全排列,在数字都确定的情况下,要学会从正常的角度思考。

#include<bits/stdc++.h>

using namespace std;

int num[7]={4, 8, 15, 16, 23,  42};

int a[7];

int main()

{

    fflush(stdout);

    cout<<"? 1 3"<<endl;

    fflush(stdout);

    cin>>a[1];

    cout<<"? 2 4"<<endl;

    fflush(stdout);

    cin>>a[2];

    cout<<"? 3 5"<<endl;

    fflush(stdout);

    cin>>a[3];

    cout<<"? 4 6"<<endl;fflush(stdout);

    cin>>a[4];

   // num[]={4, 8, 15, 16, 23,  42};

    do

    {

        if(num[0]*num[2]==a[1]&&num[1]*num[3]==a[2]&&num[2]*num[4]==a[3]&&num[3]*num[5]==a[4])

        {

            cout<<"! "<<num[0]<<" "<<num[1]<<" "<<num[2]<<" "<<num[3]<<" "<<num[4]<<" "<<num[5]<<endl;

            break;

        }

 

    }while(next_permutation(num,num+6));

    return 0;

 

}

 

#include<bits/stdc++.h>

using namespace std;

const int maxn=1e4+10;

#define ll long long

char a[maxn];

ll b[maxn];

//ll jie[maxn];

int main()

{

    int t;

    cin>>t;

    while(t--)

    {

        memset(b,0,sizeof(b));

        ll num;ll j=0;

        cin>>a; cin>>num;

        ll len=strlen(a); //cout<<a<<endl;

        ll cnt=0;

        for(int i=len-1;i>=0;i--)

        {

            b[cnt++]=(ll)(a[i]-'a'); //cout<<b[cnt-1]<<"shu"<<endl;

        }

        ll i=0;

     //   for(int j=0;j<=len-1;j++) cout<<b[j]<<endl;

        b[i]+=num;// cout<<b[2]<<endl;

        while(1)

        {

            ll temp=(b[i]+j)%26; //cout<<b[i]<<temp<<endl;

            j=(b[i]+j)/26;

            b[i]=temp;i++;

            //cout<<j<<"j"<<endl;

            //cout<<temp<<endl;

 

            if(!j)

            {

                break;

            }

            //i++;

 

 

        }

        //b[i]=j;

       // cout<<i<<endl;

        if(i>len)

        {

            for(ll j=len;j<i;j++) if(b[j])

             b[j]--;

            // else

 

 

        }

        else i=len;

        for(ll j=i-1;j>=0;j--)

        {

            cout<<char(b[j]+'a');

        }

 

        cout<<endl;

 

    }

    return 0;

}

找bug 可以从概率最大的地方去找,然后还有读题技巧。

Cf Educational Codeforces Round 65 (Rated for Div. 2)

 

B题

#include<bits/stdc++.h>

using namespace std;

int a[7]={0,4, 8, 15, 16, 23,  42};

int num[7];

 

int main()

{

    int n;

    fflush(stdout);

    cout<<"? 1 3"<<endl;

    fflush(stdout);

    cin>>num[1];

    cout<<"? 2 4"<<endl;

    fflush(stdout);

    cin>>num[2];

    //fflush(stdout);

    cout<<"? 3 5"<<endl;

    fflush(stdout);

    cin>>num[3];

    cout<<"? 4 6"<<endl;

    fflush(stdout);

    cin>>num[4];

 

    do

    {

        if(num[1]==a[1]*a[3]&&num[2]==a[2]*a[4]&&num[3]==a[3]*a[5]&&num[4]==a[4]*a[6])

        {

            cout<<"! "<<a[1]<<" "<<a[2]<<" "<<a[3]<<"  "<<a[4]<<" "<<a[5]<<" "<<a[6]<<endl;

 fflush(stdout);//不能少

break;

        }

 

    }while(next_permutation(a+1,a+7));

    return 0;

 

 

}

//格式很重要的

重要的要看清楚。

Problem C、小花梨判连通

时间限制:2000ms 空间限制:512MB

Description

小花梨给出?个点,让?位同学对这?个点任意添加无向边,构成?张图。小花梨想知道对于

每个点?,存在多少个点?(包括?本身),使得?和?在这?张图中都是连通的。

Input

第一行输入两个正整数?和?,分别表示点的个数和同学数。

接下来分成?部分进行输入,每部分输入格式相同。

每部分第一行输入一个整数??,表示第?位同学连边的数目。

接下来??行,每行两个正整数?, ?,表示第?位同学将点?和点?之间进行连接。

可能会存在重边或者自环。

(1 ≤ ? ≤ 100000,1 ≤ ? ≤ 10,1 ≤ ?, ? ≤ ?, 0 ≤ ?? ≤ 200000)

Output

输出?行,第?行输出在?张图中都和编号为?的点连通的点的数目(包括?本身)

首先看错了题目,是联通的点而不是相连的点。

POJ1321

这道题目是一个简单搜索,没想到我自己写出来了,看来是太小看自己了。

由于数据规模小,很容易过了。唯一需要注意的是,要写对对象。

#include<iostream>

#include<algorithm>

#include<cstdio>

#include<cstring>

using namespace std;

char a[10][10];

int vis[10][10];int n,k;int num;int numm=0;

int v[10];

int viss[10][10];

void dfs(int i,int j)

{

    viss[i][j]=1;v[j]=1;num++;

    if(num>=k)

    {

        numm++;

        return ;

    }

    for(int t=i+1;t<n;t++)

    for(int q=0;q<n;q++)

    {

        if(!vis[t][q]&&!v[q]&&!viss[t][q])

        {

            dfs(t,q);

            viss[t][q]=0;v[q]=0;

            num--;

        }

    }

    return ;

}

int main()

{

   // int n,k;

   // cin>>n>>k;

    while(cin>>n>>k&&!(n==-1&&k==-1))

    {

        numm=0;

        //cout<<n<<" "<<k<<endl;

        memset(v,0,sizeof(v));

        memset(vis,0,sizeof(vis));

        getchar();

        for(int i=0;i<n;i++)

        {

            scanf("%s",a[i]);

            for(int j=0;j<n;j++)

            {

               // gets(a+i);

                if(a[i][j]=='.') vis[i][j]=1;

            }

        }

        for(int i=0;i<n;i++)

        {

            for(int j=0;j<n;j++)

            {

                memset(viss,0,sizeof(viss));

                memset(v,0,sizeof(v));

                if(!vis[i][j])

                {

                    num=0;

                    dfs(i,j);

                }

            }

        }

        cout<<numm<<endl;

 

    }

    return 0;

}

POJ2251

递归复杂度到达了9e8所以加上一些运算可能超时,结果的确超时了。

要学会先用最优的啊。

#include<iostream>

#include<algorithm>

#include<cstdio>

#include<cstring>

using namespace std;

char a[31][31][31];

int vis[31][31][31];

int viss[31][31][31];

int r,l,c;int res;int sx,sy,sz,ex,ey,ez;

int dir[6][3]={0,0,1,0,0,-1,1,0,0,-1,0,0,0,-1,0,0,1,0};int re=270000;

void dfs(int i,int j,int k)

{

    viss[i][j][k]=1;res++;

   // cout<<res<<" "<<i<<" "<<j<<" "<<k<<endl;

    if(i==ex&&j==ey&&k==ez) //re=min(res,re)

    {

        re=min(re,res);

 

        return;

    }

 

    for(int q=0;q<6;q++)

    {

 

            int x=i+dir[q][0];

            int y=j+dir[q][1];

            int z=k+dir[q][2];

            if(x<0||x>=l||y<0||y>=r||z<0||z>=c)

            continue;

            if(viss[x][y][z]||vis[x][y][z]) continue;

            dfs(x,y,z);

            viss[x][y][z]=0;

            res--;

 

 

    }

    return ;

}

int main()

{

   while(cin>>l>>r>>c&&!(l==0||r==0||c==0))

   {

     //  int sx,sy,sz,ex,ey,ez;

     //cout<<l<<r<<c<<endl;

     res=0;

     re=270000;

     memset(vis,0,sizeof(vis));

     memset(viss,0,sizeof(viss));

       for(int i=0;i<l;i++)

       {

           for(int j=0;j<r;j++)

           {

               scanf("%s",a[i][j]);

               for(int k=0;k<c;k++)

               if(a[i][j][k]=='#') vis[i][j][k]=1;

               else if(a[i][j][k]=='E')

               {

                   ex=i;ey=j,ez=k;

               }

               else if(a[i][j][k]=='S') sx=i,sy=j,sz=k;

           }

 

       }

 

                   dfs(sx,sy,sz);

                 //  cout<<sx<<" "<<sy<<" "<<sz<<endl;

                  // cout<<re<<endl;

 

       if(re==270000)

       {

           cout<<"Trapped!"<<endl;

       }

       else if(sx==ex&&sy==ey&&sz==ez) cout<<0<<endl;

       else

       {

           cout<<"Escaped in "<<re-1<<" minute(s)."<<endl;

       }

 

   }

   return 0;

}

由于以前做过了,我暂时先跳过了,先做没做过的。

 

#include<iostream>

#include<algorithm>

#include<queue>

#include<cstdio>

#include<string.h>

using namespace std;

char mapp [35][35][35];

int vis[35][35][35];

int k,n,m,sx,sy,sz,ex,ey,ez;

int dir[6][3] = {{0,0,1},{0,0,-1},{0,1,0},{0,-1,0},{1,0,0},{-1,0,0}};

struct node

{

    int x,y,z,step;

};

int check(int x,int y,int z)

{

    if(x<0 || y<0 || z<0 || x>=k || y>=n || z>=m)

        return 1;

    else if(mapp[x][y][z] == '#')

        return 1;

    else if(vis[x][y][z])

        return 1;

    return 0;

 

}

int bfs()

 

{

 

    int i;

    node a,next;

    queue<node> q;

    a.x=sx;

    a.y=sy;

    a.z=sz;

    a.step=0;

    q.push(a);

    vis[sx][sy][sz]=1;

    while(!q.empty())

    {

        a=q.front();q.pop();

        if(a.x==ex&&a.y==ey&&a.z==ez) return a.step;

        for(int i=0;i<6;i++)

        {

            next=a;

            next.x=a.x+dir[i][0];

            next.y=a.y+dir[i][1];

            next.z=a.z+dir[i][2];

            if(check(next.x,next.y,next.z))

            {

                continue;

            }

            next.step=a.step+1;

            vis[next.x][next.y][next.z]=1;

            q.push(next);

        }

    }

    return 0;

}

int main()

{

    while(scanf("%d%d%d",&k,&n,&m),k+n+m)

    {getchar();

    for(int i=0;i<k;i++)

    {

        for(int j=0;j<n;j++)

        {

            scanf("%s",mapp[i][j]);

            for(int r=0;r<m;r++)

            {

                if(mapp[i][j][r]=='S')

                {

                    sx=i;

                    sy=j;

                    sz=r;

 

                }

                else if(mapp[i][j][r]=='E')

                {

                    ex=i;

                    ey=j;

                    ez=r;

                }

            }

        }

    }

    memset(vis,0,sizeof(vis));

    int ans;

    ans=bfs();

    if(ans)

    printf("Escaped in %d minute(s).\n",ans);

    else cout<<"Trapped!"<<endl;}

    return 0;

 

}

要注意复杂度,从而知道用BFS还是DFS。

 

POJ3278

#include<iostream>

#include<algorithm>

#include<queue>

#include<cstdio>

#include<string.h>

using namespace std;

const int maxx=1e6;

int s,e;

int vis[maxx+10];

struct node

{

    int x,step;

    //node(int xx,int stepp):x(xx),step(stepp){};

 

};

 

int check(int x)

{

    if(x<0||x>=maxx||vis[x])

        return 0;

    return 1;

}

int bfs(int x)

{

    queue<node> q;

    //int  s,e;

 

    node next,a;

    a.x=x;

    a.step=0;

    vis[x]=1;

    q.push(a);

    while(!q.empty())

    {   a=q.front();

        //vis[a.x]=1;

        q.pop();

        if(a.x==e)

        {

            return a.step;

        }

 

            next=a;

 

 

                next.x=a.x+1;

                if(check(next.x))

                {vis[next.x]=1;

 

                next.step=a.step+1;

                q.push(next);

                }

 

 

 

                next.x=a.x-1;

                if(check(next.x))

                {vis[next.x]=1;

 

                next.step=a.step+1;

                q.push(next);

                }

 

 

                next.x=a.x*2;

                if(check(next.x))

                {vis[next.x]=1;

 

                next.step=a.step+1;

                q.push(next);

                }

 

 

 

    }

    return -1;

 

}

int main()

{

    int ans;

    while(~scanf("%d%d",&s,&e))

    {

        memset(vis,0,sizeof(vis));

        ans=bfs(s);

        cout<<ans<<endl;

    }

    return 0;

}

这道题目只是BFS而已

POJ3279

这道题目在vj上的kuangbin比赛中被归类到了搜索, 其实它还算不上搜素, 是一道比较基础的枚举题目,和熄灯问题, 画家问题,拨钟问题是一类题, 如果单纯用爆搜或者枚举来考虑的话可能会超时,复杂度O(2^N*M) 需要一点点小的技巧

 

首先, 我们来考虑一下, 改变当前一行的只有按下当前一行或者是上一行正对着的按钮.

 

所以, 我们只用考虑第一行, 枚举第一行的开关操作, 然后与之对应的第二行就确定了, 第二行又确定了第三行...以此类推, 直到最后一行. 我们来判断是否全部归0

 

需要注意的是题中要求输出最优解, 多个最优解又要求以字典序最小的输出, 我在此用了一个字典序的状态压缩, 可以直接拿走下次用

首先注意题目类型,状态压缩,注意情况要更新。

#include<iostream>

#include<algorithm>

#include<cstring>

using namespace std;

const int maxn=20;

int a[maxn][maxn];

int cur[maxn][maxn];

int ope[maxn][maxn];

int ans[maxn][maxn];

int minsteps=1<<30;

int step;

int n,m;

void press(int x,int y)//forgotten

{

    cur[x][y]^=1;

    cur[x+1][y]^=1;

    cur[x-1][y]^=1;

    cur[x][y+1]^=1;

    cur[x][y-1]^=1;

 

}

bool solve()

{

    memcpy(cur,a,sizeof(a));//difang cuole

    for(int i=1;i<=m;i++)

    {

        if(ope[1][i])

        {

            press(1,i);

            step++;

        }

    }

    for(int i=2;i<=n;i++)

    {

        for(int j=1;j<=m;j++)

        {

            if(cur[i-1][j]==1)

            {

                ope[i][j]=1;press(i,j);

                step++;

            }

 

        }

    }

    for(int j=1;j<=m;j++)

    if(cur[n][j]==1)

    {

        return 0;

    }

    return 1;

}

int main()

{

    cin>>n>>m;

    for(int i=1;i<=n;i++)

    {

        for(int j=1;j<=m;j++)

        {

            cin>>a[i][j];

        }

    }

    for(int i=0;i<(1<<m);i++)

    {

        memcpy(cur,a,sizeof(a));//

        memset(ope,0,sizeof(ope));step=0;

        for(int j=0;j<m;j++)

        {

            ope[1][j+1]=(i>>j)&1;

          //  solve();

        }

            if(solve()>0&&step>0&&step<minsteps)

            {

                minsteps=step;

                memcpy(ans,ope,sizeof(ope));//

            }

 

 

    }

    if(minsteps<(1<<30))

    {

        for(int i=1;i<=n;i++)

        {

            for(int j=1;j<=m;j++)

            {

                cout<<ans[i][j]<<" ";

            }

            cout<<endl;

        }

    }

    else cout<<"IMPOSSIBLE"<<endl;

    return 0;

}

POJ1426

怎么都想不到是用搜索。

这博客写的很强

https://blog.csdn.net/lyy289065406/article/details/6647917

首先确定前后之间的关系,而大数的话显然就要用同余定理。然后再找规律。

敲黑板,这道题目掌握不够。

#include<iostream>

using namespace std;

int mod[550000];

int main()

{

    int n;

    while(cin>>n)

    {

        if(n==0) break;int i;

        mod[1]=1%n;

        for( i=2;mod[i-1]!=0;i++)

        {

            mod[i]=(mod[i>>1]*10+(i&1))%n;//youxianji

 

        }

        i--;

        int p=0;

        while(i)

        {

            mod[p++]=i&1;

            i>>=1;

 

        }

        while(p)

        {

            cout<<mod[--p];

        }

        cout<<endl;

    }

    return 0;

}

要注意>>优先级

POJ3126

#include<iostream>

#include<cstring>

using namespace std;

const int maxn=1e4+2;

struct m

{

    int p;

    int step;

}g[maxn];

//const int maxn=1e4+2;

bool vis[maxn];

bool judge(int i)

{

    if(i==2||i==3)

    {

        return true;

    }

    else if(i<=1||i%2==0)

    return false;

    else

    {

        for(int ii=3;ii*ii<=maxn;ii+=2)//

        {

            if(i%ii==0) return false;

        }

        return true;

    }

}

int a,b;

void bfs()

{

    int head=0;int tail=0;

    g[head].p=a;

    g[tail++].step=0;

    vis[a]=1;

    while(head!=tail+1)

    {

        m x=g[head++];

        //if()

        int shu=x.p;

        if(shu==b)

        {

            cout<<x.step<<endl;

            return ;

        }

        int ge=shu%10;

        int shi=(shu/10)%10;

        for(int i=1;i<=9;i+=2)

        {

            int q=shu/10*10+i;

            if(judge(q)&&!vis[q])

            {

                vis[q]=1;m xx;

            xx.step=x.step+1;

                xx.p=q;

                g[tail++]=xx;

            }

 

        }

        for(int i=0;i<=9;i++)

        {

            int q=shu/100*100+i*10+ge;

            if(judge(q)&&!vis[q])

            {

                vis[q]=1;m xx;

                 xx.step=x.step+1;

                xx.p=q;

                g[tail++]=xx;

            }

        }

        for(int i=0;i<=9;i++)

        {

            int q=shu/1000*1000+i*100+shi*10+ge;

            if(judge(q)&&!vis[q])

            {

                vis[q]=1;m xx;

                xx.step=x.step+1;

                xx.p=q;

                g[tail++]=xx;

            }

        }

        for(int i=1;i<=9;i++)

        {

            int q=i*1000+shu%1000;

            if(judge(q)&&!vis[q])

            {

                vis[q]=1;m xx;

                 xx.step=x.step+1;

                xx.p=q;

                g[tail++]=xx;

            }

        }

    }

    cout<<"Impossible"<<endl;

    return ;

}

int main()

{

    int t;//int a,b;

    cin>>t;

    while(t--)

    {

        cin>>a>>b;

        memset(vis,0,sizeof(vis));

        bfs();

    }

    return 0;

 

}

要自己写一遍,应该是能写出来的吧。

还有偶数和奇数缩小判断规模

POJ3087

模拟水题。

#include<iostream>

#include<cstring>

#include<map>

#include<cstdio>

using namespace std;

//map<char*,bool>book;

int main()

{

    int n;

    scanf("%d",&n);    char a[150];

    char b[150];

    char s[310];

  //  char ss[310];

    for(int i=1;i<=n;i++)

    {

 

        int t;

        //cin>>t;

        scanf("%d",&t);

        scanf("%s",a);

        scanf("%s",b);

        scanf("%s",s);

       // cin>>b;

        //cin>>s;

        int step=0;

        map<string,bool>book;//weizhi

        while(true)

        {

            int p=0;

            char ss[310];

            for(int ii=0;ii<t;ii++)

            {

                   ss[p++]=b[ii];

                   ss[p++]=a[ii];

 

 

            }

            ss[p]='\0';//

            step++;//book[ss]=1;

            //cout<<ss<<endl;

            if(!strcmp(ss,s))

            {

                cout<<i<<" "<<step<<endl;

                break;

 

            }

            if(strcmp(s,ss)&&book[ss])

            {

                cout<<i<<" "<<-1<<endl;

                break;

            }

            book[ss]=true;//weizhi

            for(int ii=0;ii<t;ii++)

            {

                a[ii]=ss[ii];

                b[ii]=ss[ii+t];

            }

            a[t]='\0';

            b[t]='\0';//

           /* for(int ii=0;ii<t;ii++)

                a[ii]=ss[ii];

                a[t]='\0';

            for(int ii=n,j=0;ii<2*t;ii++,j++)

                b[j]=ss[ii];

                b[t]='\0';*/

 

        }

    }

    return 0;

}

主要是调试程序的方法。

Lightoj1020

#include<bits/stdc++.h>

using namespace std;

#define ll long long

int main()

{

    int t;

    cin>>t;int ccase=0;

    char s[10];

    while(t--)

    {

        ll a,b;

        //cin>>a>>b;

        scanf("%lld",&a);

        scanf("%s",s);

        cout<<"Case "<<++ccase<<": ";

        if(strcmp(s,"Bob")==0)

        if(a%3==0)  printf("Alice\n");else printf("Bob\n");

 

        else

        {

            if(a%3==1) printf("Bob\n");

            else printf("Alice\n");

        }

 

 

    }

    return 0;

}

首先靠感觉是很有可能会错的,所以要从小规模考虑,分情况考虑。

然后在本人的电脑可能显示的格式是和评测的有所不同,所以不要随便忽略细节。

 

 

LightOJ 1078

同余性质

#include<bits/stdc++.h>

using namespace std;

int main()

{

    int n;

    cin>>n;int ccase=0;

    while(n--)

    {

        int a,b;

        cin>>a>>b;

        cout<<"Case "<<++ccase<<": ";

        int s=b%a;int t=1;

        while(s%a)

        {

            s=(s*10+b)%a;//个位//

            t++;

        }

        cout<<t<<endl;

    }

    return 0;

}

、LightOJ 1116

#include<bits/stdc++.h>

using namespace std;

#define ll unsigned long long

int main()

{

    int n;

    cin>>n;int ccase=0;

    while(n--)

    {

        ll a,b;

        cin>>a;

        cout<<"Case "<<++ccase<<": ";

        if(a%2==1)

        cout<<"Impossible"<<endl;

        else

        {ll t=0;

            ll aa=a;

                if(a%2==0)

                {

                    while(a%2==0)

                    {

                        a/=2;

                        t++;

                    }

                }

            cout<<a<<" "<<aa/a<<endl;

        }

    }

    return 0;

}

太简单了就不讲了

LightOJ 1148

#include<bits/stdc++.h>

using namespace std;

#define ll unsigned long long

const int maxn=1e6+10;

int a[55];

int b[maxn];

int main()

{

    int t;

    cin>>t;

    int ccase=0;

    while(t--)

    {

        int n;

        cin>>n;

        memset(b,0,sizeof(b));

        for(int i=0;i<n;i++)

        {

            cin>>a[i];

            //b[a[i]]++;

        }

    sort(a,a+n);int p=0;int res=0;

 

    while(p<n)

    {

        int q=1;

        while((p+1<n)&&a[p]==a[p+1]) q++,p++;

        int r=(q+a[p])/(a[p]+1)*(a[p]+1)-q;

        res+=r;

        p++;

 

    }

    cout<<"Case "<<++ccase<<": ";

    cout<<res+n<<endl;

 

 

    }

    return 0;

}

一遍过,太简单了。

LightOj 1179

约瑟夫问题

#include<bits/stdc++.h>

using namespace std;

#define ll unsigned long long

const int maxn=1e6+10;

int a[55];

int b[maxn];

int main()

{

    int t;

    cin>>t;

    int ccase=0;

    while(t--)

    {

        int n;int k;

        cin>>n;   cin>>k;     int s=0;//digui ,xunhuan

        for(int j=1;j<n;j++)

        {

    s=(s+k)%(j+1);

        }

 

    cout<<"Case "<<++ccase<<": ";

    cout<<(s+1)<<endl;

 

 

    }

    return 0;

}

因为nk的范围都较大所以不能直接模拟,要推导出规律f(n) = (f(n-1) + k) % n

 

//递归,从底往上

        // f[1] = 0;                 //当一个人的时候,出队人员编号为0

        // f[n] = (f[n-1] + m)%n     //m表示每次数到该数的人出列,n表示当前序列的总人数

从小规模很重要

逆向从易 到难

LightOJ1275

看清T为自变量,          一元二次方程

由此可看搜索题目是和它同等级的简单了,那我真是弱到掉渣了呢

#include<bits/stdc++.h>

using namespace std;

#define ll unsigned long long

const int maxn=1e6+10;

int a[55];

int b[maxn];

int main()

{

    int t;

    cin>>t;

    int ccase=0;

    while(t--)

    {

        int n,c;int s=0;

        cin>>n>>c;

 

        cout<<"Case "<<++ccase<<": ";

        if(n!=0)  s=c/(2*n);

        if(n==0) cout<<0<<endl;

         //int s=(c)/(2*n);//可能为小数

 

        else if(-n*s*s+s*c>=-n*(s+1)*(s+1)+(s+1)*c)//等号取不取

        cout<<s<<endl;

        else cout<<s+1<<endl;

 

 

 

    }

    return 0;

}

LightOJ 1294

#include<bits/stdc++.h>

using namespace std;

#define ll unsigned long long

const int maxn=1e6+10;

int a[55];

int b[maxn];

int main()

{

    int t;

    cin>>t;

    int ccase=0;

    while(t--)

    {

 

        ll n,m;

        cin>>n>>m;

 

 

        cout<<"Case "<<++ccase<<": ";

 

cout<<n/(2)*m<<endl;

 

    }

    return 0;

}

首先范围,然后是化简。一开始就要尽量简化。

 

POJ3414

#include<iostream>

#include<cstdio>

#include<cstring>

#include<queue>

using namespace std;

int a,b,c;bool flag=false;

const int n=110;

string str[10]={"","FILL(1)","FILL(2)","DROP(1)","DROP(2)","POUR(1,2)","PORR(2,1)"};

int vis[n][n];

struct node

{

    int x,y;//

    int step;

    string s;//记录路径

    node(int x,int y,int step,string s):x(x),y(y),step(step),s(s){}

};

void bfs()

{

    queue<node> q;

    q.push(node(0,0,0,"0"));

    vis[0][0]=1;

    while(!q.empty())

    {

        node qq=q.front();

        q.pop();

        if(qq.x==c||qq.y==c)

        {

            flag=true;

            cout<<qq.step<<endl;

 

            for(int i=0;i<qq.s.length();i++)

            {

                cout<<str[qq.s[i]-'0']<<endl;

            }

            return ;

        }

        if(qq.x<a)

        {

            if(!vis[a][qq.y])

            {

                vis[a][qq.y]=1;

                q.push(node(a,qq.y,qq.step+1,qq.s+'1'));

            }

        }

        if (qq.y<b)

        {

            if(!vis[qq.x][b])

            {

                vis[qq.x][b]=1;

                q.push(node(qq.x,b,qq.step+1,qq.s+'2'));

            }

        }

        if(qq.y!=0)

        {

            if(!vis[qq.x][0])

            {

                vis[qq.x][0]=1;

                q.push(node(qq.x,0,qq.step+1,qq.s+'4'));

            }

        }

        if(qq.x!=0)

        {

            if(!vis[0][qq.y])

            {

                vis[0][qq.y]=1;

                q.push(node(0,qq.y,qq.step+1,qq.s+'3'));

            }

        }

        if(qq.x!=0&&qq.y<b)

        {

            int xx,yy;

            if(qq.x<=b-qq.y)

            {

                 xx=0;

                 yy=qq.y+qq.x;

            }

            else

            {

                 xx=qq.x-b+qq.y;

                yy=b;

            }

            if(!vis[xx][yy])

            {

                vis[xx][yy]=1;

                q.push(node(xx,yy,qq.step+1,qq.s+'5'));

            }

        }

        if(qq.y!=0&&qq.x<a)

        {

            int xx,yy;

            if(qq.y<=a-qq.x)

            {

                 yy=0;

                 xx=qq.y+qq.x;

            }

            else

            {

                 yy=qq.y-a+qq.x;

                 xx=a;

            }

            if(!vis[xx][yy])

            {

                vis[xx][yy]=1;

                q.push(node(xx,yy,qq.step+1,qq.s+'6'));

            }

        }

    }

 

}

int main()

{

    cin>>a>>b>>c;

    bfs();

    if(!flag)

    {

        cout<<"impossible"<<endl;

    }

    return 0;

}

BFS,OJ崩了

LightOJ 1297

首先要注意解方程先要不等式,再是求导啊,要看实际意义。

#include<bits/stdc++.h>

using namespace std;

 

int main()

{

    int t;

    cin>>t;int ccase=0;

    while(t--)

    {

        double w,l;

        cin>>w>>l;

        cout<<"Case "<<++ccase<<": ";

        double a=12;

        double b=(-4)*(w+l);

        double c=(w*l);

        double in=sqrt(b*b-4*a*c);

        //double ans1=(-b+in)/2/a;

        double ans=(-b-in)/2/a;

        printf("%.6lf\n",(l-2*ans)*(w-2*ans)*ans);

    }

    return 0;

}

注意格式输出

Lightoj 1311

#include<bits/stdc++.h>

using namespace std;

int main()

 

{

    int t;

    cin>>t;int ccase=0;

 

    while(t--)

    {

        double v1,v2,v3,a1,a2;double t;

        //t=max()

        cin>>v1>>v2>>v3>>a1>>a2;

        t=max(v1/a1,v2/a2);//keyi buyiyangchang

        cout<<"Case "<<++ccase<<": ";

        printf("%.6lf ",v1*v1/2/a1+v2*v2/2/a2);

        printf("%.6lf\n",t*v3);

    }

    return 0;

}

可以不同时停下来。还是思路可能会错。

Hdu 1024

首先定义dp[i][j]为状态: 在前j个数中恰好选出i组数的最大和

得出状态转移方程dp[j][j]=max(dp[i][j−1],dp[i][j−1]+a[j],dp[i−1][k]+a[j](0&lt;k&lt;j)) dp[j][j] = max(dp[i][j-1], dp[i][j-1]+a[j], dp[i-1][k]+a[j](0&lt;k&lt;j)    )dp[j][j]=max(dp[i][j−1],dp[i][j−1]+a[j],dp[i−1][k]+a[j](0<k<j))

意义依次为不取第j个数, 取第j个数归入当前组, 取第j个数归入新的组.

显然n2 n^2n

2

 的复杂度, 不管是空间还是时间都无法通过, 我们考虑优化, 首先dp[i][j-1]和 dp[i-1][k]+aj其实和dp[i-1][k]+aj含义是相似的, 试想不取当前这个数, 其实就是在之后的某个地方开了新的组把这个数弹出来了.

而且和背包问题一样, 只和dp[i-1]这一层有关, 我们用一维数组来滚动就可以啦, 顺序不变

最后dp[i-1][k]其实就是上一组j之前最大的dp, 我们用一个数组来存一下就好了

首先要注意无论如何都可以分为i组。

先写递推式,再化简。那么,然后再直接前j-1求最大值,存在数组里

要注意每次的初始化

#include<bits/stdc++.h>

using namespace std;

const int maxn=1e6+10;

const int mm=0x7fffffff;

int dp[maxn];

int num[maxn];

int pre[maxn];//

int main()

{

    int n;int m;

    while(cin>>m>>n)

    {

        memset(dp,0,sizeof(dp));

        memset(pre,0,sizeof(pre));

        int temp=-mm;

        for(int i=1;i<=n;i++)

        cin>>num[i];

        for(int i=1;i<=m;i++)

        {

            temp=-mm;//

            for(int j=i;j<=n;j++)

            {

                dp[j]=max(dp[j-1],pre[j-1])+num[j];

                pre[j-1]=temp;

                temp=max(temp,dp[j]);

            }

        }

        cout<<temp<<endl;

    }

    return 0;

}

Hdu1029

#include<bits/stdc++.h>

using namespace std;

const int maxn=1e6+2;

int a[maxn];

int  main()

{

    int n;

    while(cin>>n)

    {

        for(int i=1;i<=n;i++)

        cin>>a[i];

        sort(a+1,a+n+1);

        cout<<a[(n+1)/2]<<endl;

    }

    return 0;

}

好像可以dp做,但是原谅我不想那么麻烦,留待以后去做。

Hdu 1069

#include<bits/stdc++.h>

using namespace std;

struct node

{

    int l,w,h;

}nod[181];

int dp[181];

bool cmp(node a,node b)

{

    if(a.l==b.l) return a.w<b.w;

    return a.l<b.l;

 

}

 

int main()

{

    int n;int ccase=0;

    while(scanf("%d",&n)&&n)

    {

        memset(dp,0,sizeof(dp));int len=0;

        for(int i=1;i<=n;i++)

        {

            int x,y,z;

            cin>>x>>y>>z;

            nod[len].l=x;nod[len].w=y;nod[len++].h=z;

            nod[len].l=x;nod[len].w=z;nod[len++].h=y;

            nod[len].l=y;nod[len].w=x;nod[len++].h=z;

            nod[len].l=y;nod[len].w=z;nod[len++].h=x;

            nod[len].l=z;nod[len].w=y;nod[len++].h=x;

            nod[len].l=z;nod[len].w=x;nod[len++].h=y;

 

 

 

        }

        sort(nod,nod+len,cmp);dp[0]=nod[0].h;

        for(int i=1;i<len;i++)

        {

            int mm=0;

            for(int j=0;j<i;j++)

            {

                if(nod[i].l>nod[j].l&&nod[i].w>nod[j].w)

                mm=max(mm,dp[j]);

            }

            dp[i]=nod[i].h+mm;

        }

        int mmm=0;

        for(int i=0;i<len;i++)

        mmm=max(mmm,dp[i]);//

        cout<<"Case "<<++ccase<<": "<<"maximum height = ";

        cout<<mmm<<endl;

 

    }

    return 0;

}

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值