zoukankan      html  css  js  c++  java
  • [3.3校内训练赛]

    我好菜啊都不会  hzwer又出丧题啦 

    ---------------

    A.[百练2812] 恼人的青蛙

    给丁一张r*c的图,上面有最多n个青蛙脚印,一个青蛙行走的路线是一条直线,且间隔距离相同,最少行走3个点。

    求可能的青蛙走过的踩过最多脚印的路线的脚印数量。

    r,c,n<=5000

    做法:枚举两个点,check一下。

    加一些剪枝,比如如果目前这条直线即使可行也不会比答案优秀,我们就可以退出了。

    还可以把点按照横坐标排序,每次如果因为横坐标相差过大导致出现剪枝1的情况,就可以不搜前面这个点了,因为后面的点相差显然更大。

    然后加了跑的飞快 165ms 就过了 复杂度O(能过)

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    
    inline int abs(int x){return x<0?-x:x;}
    
    bool yes;
    bool b[5005][5005];
    int r,c;
    int n,u,v,ans=0,num,xx,yy;
    struct node{
        int x,y;
    }s[5005];
    
    bool cmp(node x,node y){return x.x<y.x;}
    
    int main()
    {
        r=read();c=read();n=read();
        for(register int i=1;i<=n;i++)
        {
            s[i].x=read();s[i].y=read();
            b[s[i].x][s[i].y]=1;
        }
        sort(s+1,s+n+1,cmp);
        for(register int i=1;i<=n;i++)
            for(register int j=i+1;j<=n;j++)
                if(abs(s[i].x-s[j].x)*ans<=r)
                {
                    if(abs(s[i].y-s[j].y)*ans>c)continue;
                    num=0;yes=true;
                    for(xx=s[i].x,yy=s[i].y;xx>0&&yy>0&&xx<=r&&yy<=c;xx+=s[i].x-s[j].x,yy+=s[i].y-s[j].y)
                        if(!b[xx][yy]){yes=false;break;}else ++num;
                    if(yes)for(xx=s[j].x,yy=s[j].y;xx>0&&yy>0&&xx<=r&&yy<=c;xx+=s[j].x-s[i].x,yy+=s[j].y-s[i].y)
                        if(!b[xx][yy]){yes=false;break;}else ++num;
                    if(yes) ans=max(ans,num);
                }
                else break;
        printf("%d
    ",ans>2?ans:0);
        return 0;
    }

    C.[hdu2197]本原串

    求长度为n的没有循环节的二进制串的个数。n<=10^8

    题解:筛出所有因数,然后容斥原理

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #define mod 2008
    using namespace std;
    
    int s[10005],num[10005],n,cnt;
    int ans=0;
    
    int pow(int x,int p)
    {
        int sum=1;
        for(int i=x;p;p>>=1,i=(i*i)%mod)if(p&1)
              sum=(sum*i)%mod;
        return sum;
    }
    
    int main()
    {
        while(scanf("%d",&n)!=EOF)
        {
            cnt=0;ans=pow(2,n);
            for(int i=1;i<=sqrt(n);i++)
                if(n%i==0)
                {
                    s[++cnt]=i;num[cnt]=-1;
                    if(i*i!=n)s[++cnt]=n/i,num[cnt]=-1;    
                }
            sort(s+1,s+cnt+1);
            for(int i=cnt-1;i;i--)
                for(int j=1;j<i;j++)
                    if(s[i]%s[j]==0) num[j]-=num[i];
            for(int i=1;i<cnt;i++)ans=(ans+1000*mod+num[i]*pow(2,s[i]))%mod;
            cout<<ans<<endl;
        }
        return 0;
    } 

    D.Poj2112

    有c个奶牛,n个点,每个点最多m头牛,每头牛要去一个点,给丁所有牛和点的距离,求所有牛都有点去的时候最大距离的最小值  

    c<=200,n<=30,m<=15

    二分答案,然后网络流check一下

    因为是临时换题了,所以不知道还有这道大水题...没去切.....但是看看就会做(原来的D题貌似是dancing link)

    E.有n个人,m个限制条件,每个限制条件要求ai比bi更前。n<=200000,m<=400000

    你要在限制的基础上,安排一个顺序,让1的位置尽量小,然后2的位置尽量小........

    题解:倒着建图,堆+括扑排序,倒着输出

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #define ll long long
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    
    priority_queue<int> q;
    
    int n,m,cnt=0;
    struct edge{
        int to,next;
    }e[400005];
    int head[200005];
    int to[200005];
    int ans[200005];
    
    void ins(int f,int t)
    {
        e[++cnt].next=head[f];head[f]=cnt;
        e[cnt].to=t;
    }
    
    int main()
    {
        n=read();m=read();
        for(int i=1;i<=m;i++)
        {
            int u=read(),v=read();
            ins(v,u);to[u]++;
        }
        for(int i=1;i<=n;i++)if(!to[i])q.push(i);
        for(int i=1;i<=n;i++)
        {
            int x=q.top();q.pop();
            ans[i]=x;
            for(int i=head[x];i;i=e[i].next){--to[e[i].to];if(!to[e[i].to])q.push(e[i].to);}
        }
        for(int i=n;i;i--)printf("%d ",ans[i]);
        return 0;
    }

     G.[bzoj3998]弦图

    给定一个长度为n的字符串,求它的第k大子串(给定T,如果T=1那么不同位置相同子串可重复计算,T=0则不行) n<=500000,k<=10^9

    题解:后缀自动机模板题....

    去黄学长博客逛了逛发现原来可以直接用计数排序来求括扑序....

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    
    int c[1000005][26],step[1000005],fail[1000005];
    long long val[1000005],sum[1000005];
    int v[500005],rk[1000005];
    char s[500005];
    int cnt=1,last=1,T,k,n;
    
    void ins(int x)
    {
        int p=last,np=++cnt;step[np]=step[last]+1;val[np]=1;
        for(;p&&!c[p][x];p=fail[p])c[p][x]=np;
        if(!p)fail[np]=1;
        else
        {
            int q=c[p][x];
            if(step[q]==step[p]+1) fail[np]=q;
            else
            {
                int nq=++cnt;step[nq]=step[p]+1;
                for(int i=0;i<26;i++)c[nq][i]=c[q][i];
                fail[nq]=fail[q];fail[q]=fail[np]=nq;
                for(;c[p][x]==q;p=fail[p])c[p][x]=nq;
            }
        }
        last=np;
    }
    
    void work()
    {
        for(int i=1;i<=cnt;i++)v[step[i]]++;
        for(int i=1;i<=n;i++)v[i]+=v[i-1];
        for(int i=cnt;i;i--) rk[v[step[i]]--]=i;
        if(T==1)for(int i=cnt;i;i--) val[fail[rk[i]]]+=val[rk[i]];
        else for(int i=cnt;i;i--) val[rk[i]]=1;
        val[1]=0;
        for(int i=cnt;i;i--)
        {
            sum[rk[i]]=val[rk[i]];
            for(int j=0;j<26;j++)sum[rk[i]]+=sum[c[rk[i]][j]];
        }
    }
    
    void dfs(int x,int k)
    {
        if(k<=val[x])return;
        k-=val[x];
        for(int j=0;j<26;j++)
        if(int t=c[x][j])
        {
            if(sum[t]>=k) {putchar(j+'a');dfs(t,k);return;}
            else k-=sum[t];
        }
    }
    
    int main()
    {
        scanf("%s",s+1);n=strlen(s+1);
        for(int i=1;s[i];ins(s[i++]-'a'));
        scanf("%d%d",&T,&k);
        work();
        if(sum[1]<k)puts("-1");
        else dfs(1,k);
        return 0;
    }
  • 相关阅读:
    python奇技淫巧——max/min函数的用法
    mysql中InnoDB存储引擎的行锁和表锁
    supervisor进程管理工具
    Tornado源码分析 --- Cookie和XSRF机制
    Tornado源码分析 --- Redirect重定向
    Tornado源码分析 --- 静态文件处理模块
    Tornado源码分析 --- Etag实现
    Python环境管理--virtualenvwrapper
    记录
    由 '' in 'abc' return True 引发的思考----Python 成员测试操作
  • 原文地址:https://www.cnblogs.com/FallDream/p/acm33.html
Copyright © 2011-2022 走看看