首页 > 代码库 > Week SP1:2014/11/2

Week SP1:2014/11/2

一直拖到现在才写,中间还有几道没看。。

A:Aizu 0009 Prime Number:素数筛选,注意可能爆内存!!。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
typedef long long LL;
using namespace std;
#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define CLEAR( a , x ) memset ( a , x , sizeof a )
const int N=1e7;
int vis[N];
void initPrime()
{
    int num = 0, m = sqrt (N + 0.5);
    REPF(i,1,N)   vis[i]=1;
    for (int i = 2; i <= m; ++i)
        if (vis[i] == 1)
            for (int j = i * i; j <= N; j += i) vis[j] = 0;
    vis[1]=0;
    for(int i=2;i<=N;i++)
         vis[i]+=vis[i-1];
//    for(int i=2;i<=10;i++)
//        cout<<"233  "<<sum[i]<<endl;
}
int main()
{
    int n;
    initPrime();
    while(~scanf("%d",&n))
        printf("%d\n",vis[n]);
    return 0;
}
B:Aizu 2224 Save your cat...

C:CF   250A Paper Work

题意:求最少的连续段是每段的负数个数不超过2。乱搞。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
typedef long long LL;
using namespace std;
#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define CLEAR( a , x ) memset ( a , x , sizeof a )
int a[110],n;
int num[110];
int main()
{
    while(~scanf("%d",&n))
    {
        REPF(i,1,n)
          scanf("%d",&a[i]);
        CLEAR(num,0);
        int cnt=0;
        int l=0;
        int m=0;
        REPF(i,1,n)
        {
            m++;
            if(a[i]<0)
               cnt++;
            if(cnt==2)
            {
                cnt=0;int j;
                for(j=i+1;j<=n;j++)
                {
                    if(a[j]<0)  break;
                    else  m++;
                }
                num[l++]=m;
                i=j-1;
                m=0;
            }
            if(i==n&&cnt==1)  num[l++]=m;
        }
        if(l==0)
        {
            printf("%d\n%d\n",1,n);
            continue;
        }
        printf("%d\n",l);
        REP(i,l)
           printf(i==l-1?"%d\n":"%d ",num[i]);
    }
}
D:CF 126B Password:

题意:求一个最长字串是它的前缀,后缀,和中间的一个字串相同

KMP做法:

#include <iostream>
#include <cstdio>
#include <cstring>
#define LMT 1000005
using namespace std;
int hash[LMT],next[LMT],len;
char str[LMT];
void init(void)
{
    int i=0,j=-1;
    next[0]=-1;
    while(i<len)
    {
        if(j==-1||str[i]==str[j])
        {
            i++;j++;next[i]=j;
        }
        else j=next[j];
    }
    for(i=0;i<len;i++)
    {
//      cout<<"2333   "<<next[i]<<endl;
       hash[next[i]]++;
    }
}
int main()
{
    int i;
    scanf("%s",str);
    len=strlen(str);
    init();
    i=len;
    while(next[i]>0)//对应aaa这种情况
    {
       if(hash[next[i]])
       {
         for(int j=0;j<next[i];j++)
           printf("%c",str[j]);
         printf("\n");
         return 0;
       }
       i=next[i];
    }
    printf("Just a legend\n");
    return 0;
}

F:CF 303 D Biridian Forest

题意:迷宫中到达出口,中间有人决斗,问最少的打架次数.反向BFS即可.

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
typedef long long LL;
using namespace std;
#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define CLEAR( a , x ) memset ( a , x , sizeof a )
const int maxn=1100;
char mp[maxn][maxn];
int val[maxn][maxn];
int dis[maxn][maxn];
int vis[maxn][maxn];
int dr[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
int n,m,ex,ey;
void BFS()
{
    pair<int,int>st;
    CLEAR(vis,0);
    vis[ex][ey]=1;
    dis[ex][ey]=1;
    queue<pair<int,int> >q;
    int dd=0x7fffff;
    int num=0;
    q.push(make_pair(ex,ey));
    while(!q.empty())
    {
        st=q.front();
        q.pop();
        if(dis[st.first][st.second]>dd)
            break;
        REP(i,4)
        {
            int xx=st.first+dr[i][0];
            int yy=st.second+dr[i][1];
            if(mp[xx][yy]!='T'&&!vis[xx][yy]&&xx>=0&&xx<n&&yy>=0&&yy<m)
            {
                dis[xx][yy]=dis[st.first][st.second]+1;
                vis[xx][yy]=1;
                if(dis[xx][yy]<=dd)
                    num+=val[xx][yy];
                if(mp[xx][yy]=='S')
                    dd=dis[xx][yy];
                q.push(make_pair(xx,yy));
            }
        }
    }
    printf("%d\n",num);
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        REP(i,n)
           scanf("%s",mp[i]);
        CLEAR(val,0);
        REP(i,n)
        {
            REP(j,m)
            {
                if(mp[i][j]=='E')
                {
                    ex=i;
                    ey=j;
                }
                if(mp[i][j]>='0'&&mp[i][j]<='9')
                    val[i][j]=mp[i][j]-'0';
            }
        }
        BFS();
    }
    return 0;
}

G CF 215 D  Hot Days.

坑题,中间无限爆long long ,最后考虑极值在两端出取得。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
typedef long long LL;
using namespace std;
#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define CLEAR( a , x ) memset ( a , x , sizeof a )
const int maxn=1e5+100;
LL t[maxn],T[maxn],x[maxn],cost[maxn];
int n,m;
LL solve(int f,LL xx)
{
    int l=1,r=m/xx+(m%xx?1:0);
    LL maxnn;
    if(m<=xx)   maxnn=cost[f];
    else   maxnn=cost[f]+x[f]*m;
    if((LL)r*xx<m)
        maxnn=min(maxnn,(LL)r*cost[f]+((LL)(m-xx*r)+xx)*x[f]);
    else
        maxnn=min(maxnn,(LL)r*cost[f]);
    return maxnn;
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
         LL sum=0;
         REPF(i,1,n)
            scanf("%I64d%I64d%I64d%I64d",&t[i],&T[i],&x[i],&cost[i]);
         REPF(i,1,n)
         {
             if(T[i]-t[i]>0)
             {
                LL xx=T[i]-t[i];
                sum+=solve(i,xx);
             }
             else
                sum+=((LL)m*x[i]+cost[i]);
         }
         printf("%I64d\n",sum);
    }
    return 0;
}

I:HDU 1353/POJ 2581  竟然是暴力水题,我一直在在想怎么记录路径。其实开始也想到暴力,最后不敢写。POJ上必须C++交。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
typedef long long LL;
using namespace std;
#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define CLEAR( a , x ) memset ( a , x , sizeof a )

int main()
{
    int num1,num2,num3,num4;
    int a,b,c,d;double x;
    while(~scanf("%lf%d%d%d%d",&x,&num1,&num2,&num3,&num4))
    {
        int n=(int)(x*100);
//        cout<<n<<endl;
        int flag=0;
        for(int i=0;i<=num4;i++)
        {
            for(int j=0;j<=num3;j++)
            {
                for(int k=0;k<=num2;k++)
                {
                    for(int l=0;l<=num1;l++)
                    {
                        if(i+5*j+10*k+25*l==n)
                        {
                            a=l;b=k;c=j;d=i;
                            flag=1;
                            break;
                        }
                    }
                    if(flag)  break;
                }
                if(flag)   break;
            }
            if(flag)  break;
        }
        if(flag)   printf("%d %d %d %d\n",a,b,c,d);
        else   printf("NO EXACT CHANGE\n");
    }
    return 0;
}

J:HDU 1595 find the longest of the shortest

Dijkstra求一遍记录前驱后,拆边记录最大的值。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
typedef long long LL;
using namespace std;
#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define CLEAR( a , x ) memset ( a , x , sizeof a )
const int maxn=1100;
int mp[maxn][maxn];
int vis[maxn],dis[maxn];
int pre[maxn];
int n,m;

void dijkstra(int x)
{
    int pos;
    CLEAR(vis,0);
    REPF(i,1,n)
       dis[i]=mp[1][n];
    dis[1]=0;
//    vis[1]=1;
    REPF(i,1,n)
    {
        pos=-1;
        REPF(j,1,n)
        {
            if(!vis[j]&&(pos==-1||dis[pos]>dis[j]))
                pos=j;
        }
        vis[pos]=1;
        REPF(j,1,n)
        {
            if(!vis[j]&&dis[j]>dis[pos]+mp[pos][j])
            {
                dis[j]=dis[pos]+mp[pos][j];
                if(x)     pre[j]=pos;
            }
        }
    }
}

int main()
{
    int u,v,w;
    while(~scanf("%d%d",&n,&m))
    {
        CLEAR(mp,0x3f3f3f);
//        REPF(i,1,n)  mp[i][i]=0;
        CLEAR(pre,-1);
        while(m--)
        {
            scanf("%d%d%d",&u,&v,&w);
            if(mp[u][v]>w)   mp[u][v]=mp[v][u]=w;
//            cout<<mp[u][v]<<endl;
        }
        dijkstra(1);
//        cout<<"2333  "<<dis[n]<<endl;
        int dd=dis[n];
        for(int i=n;i!=1;i=pre[i])
        {
            int t=mp[i][pre[i]];
//            cout<<"666  "<<endl;
            mp[i][pre[i]]=mp[pre[i]][i]=0x3f3f3f;
            dijkstra(0);
            if(dis[n]>dd)
                dd=dis[n];
            mp[i][pre[i]]=mp[pre[i]][i]=t;
        }
        printf("%d\n",dd);
    }
    return 0;
}



Week SP1:2014/11/2