ZF_20160702_Region2013长春

本文精选了多项算法竞赛题目并提供了详细的解决方案,包括模拟进制运算、二分查找、高斯消元、字符串哈希、LCA问题等多种算法。通过这些实战案例,展示了算法设计与实现的具体过程。

B题
模拟(1+/5)/2进制,以前写过。

//{
using namespace std;
//#pragma warning(disable:4996)
//#pragma comment(linker,"/STACK:102400000,102400000")
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<cmath>
#define ll         long long
#define clr(x,y)   memset(x,y,sizeof(x))
#define ww         while
#define r1(i,a,b)  for(int i=a;i< b;i++)
#define r2(i,a,b)  for(int i=a;i<=b;i++)
#define r3(i,a,b)  for(int i=a;i> b;i--)
#define r4(i,a,b)  for(int i=a;i>=b;i--)
#define r5(i,a,n)  for(int i=1;i<=n;i++)sf1(a[i])
#define r6(i,a,s,t)  for(int i=s;i<=t;i++)pf("%d%c",a[i],i-(t)?' ':'\n')
#define ss(x)      sf("%s",x)
#define sf1(x)     sf("%d",&x)
#define sf2(x,y)   sf("%d%d",&x,&y)
#define sf3(x,y,z) sf("%d%d%d",&x,&y,&z)
#define pd(x,y)    printf("%d%c",x,(char)y)
#define sf         scanf
#define pf         printf
#define pct(x)     __builtin_popcount(x)
#define ctz(x)     __builtin_ctz(x)
const int inf=0x3f3f3f3f;
const ll MOD=1e9+7;
const int o=200;
struct STC
{
    int a[420],l,r;
    STC(){clr(a,0);}
    void E(){clr(a,0);a[o]=1;l=r=o;}
    void out()
    {
        r4(i,r,o)printf("%d",a[i]);putchar('.');r4(i,o-1,l)printf("%d",a[i]);
    }
    void get(char c[])
    {
        int len=strlen(c);
        int pos;
        r1(i,0,len)if(c[i]=='.')pos=i;
        r=pos+199;l=pos+201-len;
        r1(i,0,pos)a[r-i]=c[i]-'0';
        r1(i,pos+1,len)a[pos+200-i]=c[i]-'0';
    }
    void add(int p)
    {
        a[p]++;
        ww(a[p]==2)
        {
            a[p]=0;
            a[p-2]++;a[p+1]++;
            p-=2;
        }
        r4(i,400,2)if(a[i]&&a[i-1])a[i]=a[i-1]=0,a[i+1]=1,i=i+3;
        l=400,r=-1;
        r2(i,2,400)if(a[i]){l=min(l,i),r=max(i,r);}//printf("%d      ",i);}
    }
};
STC two,th;
STC add(STC x,STC y)
{
    r2(i,y.l,y.r)if(y.a[i])x.add(i);
    return x;
}
STC s[40];
bool ok[31];
int main()
{
    int n;
    s[1].get("10.01");
    r2(i,2,32)s[i]=add(s[i-1],s[i-1]);
    ww(~sf1(n))
    {
        if(n<=1)pd(n,10);
        else
        {
            clr(ok,0);
            r2(i,0,30)if((1<<i)&n)ok[i]=1;
            int st;
            r2(i,1,30)if(ok[i]){st=i;break;}
            STC tm=s[st];
            r2(i,st+1,30)if(ok[i]){tm=add(tm,s[i]);}
            if(n&1)tm.add(200);
            tm.out();puts("");
        }
    }
}

C题
二分

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ll long long
using namespace std;
ll n,s,t;
double p;
ll a[2000010],b[2000010];
ll d[50];
ll get(ll val)
{
    ll ret=0;
    for(ll mask=0;mask<(1<<s);mask++)
    {
        ret+=upper_bound(b,b+(1<<t),val-a[mask])-b;
    }
    return ret;
}
int main()
{
    int cas;scanf("%d",&cas);
    while(cas--)
    {
        scanf("%lld%lf",&n,&p);
        for(ll i=1;i<=n;i++)scanf("%lld",&d[i]);
        if(p<=0.0)
        {
            puts("0");continue;
        }
        s=n/2,t=n-s;
        for(ll mask=0;mask<(1<<s);mask++)
        {
            ll x=0;
            for(ll j=0;j<s;j++)if(mask&(1<<j))x+=d[j+1];
            a[mask]=x;
        }
        sort(a,a+(1<<s));a[1<<s]=1e12;
        for(ll mask=0;mask<(1<<t);mask++)
        {
            ll x=0;
            for(ll j=0;j<t;j++)if(mask&(1<<j))x+=d[s+j+1];
            b[mask]=x;
        }
        sort(b,b+(1<<t));b[1<<t]=1e12;
        ll l=1,r=40000,mid;
        while(l<r)
        {
            mid=l+r>>1;
            if(get(mid)/((double)(1LL<<n))<p)l=mid+1;
            else r=mid;
        }
        ll ans=1e16;
        for(ll mask=0;mask<(1<<s);mask++)
        {
            ll pos=lower_bound(b,b+(1<<t),l-a[mask])-b;
            ans=min(ans,b[pos]+a[mask]);
        }
        printf("%lld\n",ans);
    }
}

F题
题目中说n<=100,其实比100大。
高斯消元

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;


int n,m,in[300],g[300][300];
vector<int>V[300];

namespace G
{
    const int _=300;
    double eps=1e-9;
    typedef double ml;
    ml a[_][_],X[_];
    bool Gauss(ml a[][_],int va,ml X[],int equ,int add=0)
    //va是未知量的个数,equ是式子个数,add是增广矩阵
    {
        for(int r=1;r<=equ;r++)
        {
            int mx=r;
            for(int i=r+1;i<=equ;i++)if(fabs(a[mx][r])<fabs(a[i][r]))mx=i;
            if(fabs(a[mx][r])<eps)return 0;
            if(mx!=r)for(int i=r;i<=va+1+add;i++)swap(a[mx][i], a[r][i]);
            for(int i=r+1;i<=va+1+add;i++)a[r][i]/=a[r][r]; a[r][r]=1;//化简
            for(int i=1;i<=equ;i++)if(i!=r)
            {
                for(int j=r+1;j<=va+1+add;j++)a[i][j]-=a[r][j]*a[i][r];
                a[i][r]=0;
            }
        }
        return 1;
    }
    void out(int n,int m)
    {
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)printf("%lf ",a[i][j]);puts("");
        }
    }
    int sta[300];
    void Go()
    {
        memset(a,0,sizeof a);
        memset(X,0,sizeof X);
        for(int i=1;i<n;i++)
        {
            int len=V[i].size();
            for(int j=0;j<len;j++)
            {
                int v=V[i][j];
                a[i][v]=1.0/in[v];
            }
            a[i][i]=-1;a[i][n+1]=0;
        }
        for(int i=1;i<=n+1;i++)a[n][i]=1;
        int add=0;
        for(int k=1;k<n;k++)if(g[n][k]==0)
        {
            sta[++add]=k;
            for(int i=1;i<n;i++)
            {
                a[i][n+1+add]=g[n][i]?1.0/(in[n]+1):0;
            }
            a[k][n+1+add]=1.0/(in[n]+1);
            a[n][n+1+add]=1.0;
        }
        if(!Gauss(a,n,X,n,add))
        {
            puts("INF");return;
        }
        double now=fabs(a[n][n]);
        int ans=-1;
        for(int i=n+2;i<=n+1+add;i++)
        {
            if(now>fabs(a[n][i]))
                now=fabs(a[n][i]),ans=sta[i-n-1]-1;
        }
        printf("%d %d\n",1,ans);
    }
}
int main()
{
    int cas;scanf("%d",&cas);
    while(cas--)
    {
        scanf("%d%d",&n,&m);
        memset(g,0,sizeof g);
        memset(in,0,sizeof in);
        for(int i=1;i<=n;i++)V[i].clear();
        while(m--)
        {
            int x,y;scanf("%d%d",&x,&y);
            if(x!=y)g[x+1][y+1]=1;
        }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            {
                if(i!=j&&g[i][j])
                {
                    in[i]++;
                    V[j].push_back(i);
                }
            }
        G::Go();
    }
}

I题
字符串哈希

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#define ll long long
using namespace std;
ll mod=1e12+7,t=1331;
ll len,m,l,ans;
char c[100010];
ll sta[100010],top;
map<ll,ll>M;
ll jie[100010];
int main()
{
    jie[0]=1;
    for(ll i=1;i<=100000;i++)jie[i]=jie[i-1]*t%mod;
    while(~scanf("%lld%lld",&m,&l))
    {
        scanf("%s",c+1);
        ans=0;
        len=strlen(c+1);
        for(ll i=1;i<=l&&i+m*l-1<=len;i++)
        {
            if(i==1)
            {
                top=0;
                ll tmp=0,num=0;
                for(ll j=i;j<=len;j++)
                {
                    ++num;
                    tmp=(tmp+c[j]*jie[l-num])%mod;
                    if(num==l)
                    {
                        sta[++top]=tmp;
                        tmp=0;num=0;
                    }
                }
            }
            else
            {
                top=(len-i+1)/l;
                for(ll j=1;j<=top;j++)
                {
                    sta[j]-=c[i-1+l*(j-1)]*jie[l-1]%mod;
                    sta[j]=(sta[j]%mod+mod)%mod;
                    sta[j]=sta[j]*t%mod;
                    sta[j]=(sta[j]+c[i+l*j-1])%mod;
                }
            }
            ll ban=0;M.clear();
            for(ll j=1;j<=top;j++)
            {
                if(M[sta[j]]&&j-M[sta[j]]<m)
                {
                    ban=max(ban,M[sta[j]]+m);
                }
                M[sta[j]]=j;
                if(j>=m&&ban<=j)ans++;
            }
        }
        printf("%lld\n",ans);
    }
}

J题
LCA问题,树上三个点,问各个点统治的点个数。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;

int n,m;

namespace G
{
    const int _=100010;
    vector<int>V[_];
    int fa[_][21],dep[_],siz[_];
    void dfs(int u,int f)
    {
        for(int i=1;i<=20;i++)fa[u][i]=fa[fa[u][i-1]][i-1];
        int len=V[u].size();
        siz[u]=1;
        for(int i=0;i<len;i++)
        {
            int v=V[u][i];
            if(v==f)continue;
            fa[v][0]=u;
            dep[v]=dep[u]+1;
            dfs(v,u);
            siz[u]+=siz[v];
        }
    }
    void init()
    {
        fa[1][0]=0;dep[1]=1;
        dfs(1,0);
    }
    int fa_k(int u,int k)
    {
        for(int i=0;i<=20;i++)if(k&(1<<i))u=fa[u][i];return u;
    }
    int query(int a,int b)
    {
        if(dep[a]>dep[b])swap(a,b);
        b=fa_k(b,dep[b]-dep[a]);
        if(a==b)return a;
        for(int i=20;i>=0;i--)
        {
            if(fa[a][i]!=fa[b][i])
            {
                a=fa[a][i];b=fa[b][i];
            }
        }
        return fa[a][0];
    }
    struct STC{
        int flag,u;
    };
    STC getMid(int a,int b,int ab)
    {
        int tmp=dep[a]+dep[b]-2*dep[ab];
        STC t;
        if(dep[a]>=dep[b])
            t.flag=1,t.u=fa_k(a,(tmp-1)/2);
        else
            t.flag=2,t.u=fa_k(b,tmp/2);
        return t;
    }
    int cal(int a,int b,int c,int ab,int ac)
    {
        STC abm=getMid(a,b,ab),acm=getMid(a,c,ac);
        if(abm.flag==1&&acm.flag==1)
            return dep[abm.u]>dep[acm.u]?siz[abm.u]:siz[acm.u];
        else if(abm.flag==2&&acm.flag==2)
        {
            if (dep[abm.u]<dep[acm.u]) swap(abm,acm);
            if (query(abm.u,acm.u)==acm.u) return n-siz[acm.u];
            return n-siz[abm.u]-siz[acm.u];
        }
        else
        {
            if(abm.flag==2)swap(abm,acm);
            int tmp=query(abm.u,acm.u);
            if(tmp==abm.u)return siz[abm.u]-siz[acm.u];
            else return siz[abm.u];
        }
    }
    void Go()
    {
        int cas;scanf("%d",&cas);
        while(cas--)
        {
            scanf("%d",&n);
            for(int i=1;i<=n;i++)V[i].clear();
            for(int i=1;i<n;i++)
            {
                int x,y;scanf("%d%d",&x,&y);
                V[x].push_back(y);V[y].push_back(x);
            }
            init();
            scanf("%d",&m);
            while(m--)
            {
                int a,b,c;
                scanf("%d%d%d",&a,&b,&c);
                int ab=query(a,b),ac=query(a,c),bc=query(b,c);
                printf("%d %d %d\n",cal(a,b,c,ab,ac),cal(b,a,c,ab,bc),cal(c,a,b,ac,bc));
            }
        }
    }
};
int main()
{
    G::Go();
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值