2017-2-15做题记录

[9018]1930 国家

题目大意:给定A、B序列,A序列中的数若满足a xor b%2=1则连边,B序列中数若满足a xor b%2=0或a or b二进制下有奇数个1则连边,再给出A和B的连边关系,求最大团。(数据组1:A<=80,B<=100;数据组2:A<=5,B<=1500)

思路:这题是本校以前某次测试的题,当时看了看感觉不可做就跳过了……观察发现,最大团中A序列的点不会超过2个(因为a和b必须一奇一偶才能连边,奇或偶超过1个必然不是团),于是可以先枚举取A中的哪些点,然后取出相连的B中的点,按奇偶分成二分图,考虑最小割,若二分图两边一对点或起来有偶数个1则不能一起选入答案,连INF,然后跑一遍模板就能A了。复杂度O(能过)。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline int read()
{
    int x=0;char c;
    while((c=getchar())<'0'||c>'9');
    for(;c>='0'&&c<='9';c=getchar())x=(x<<3)+(x<<1)+c-'0';
    return x;
}
#define MA 80
#define MB 1500
#define MV 1500
#define ME 562500
#define S MV+1
#define T MV+2
#define INF 0x3fffffff
struct edge{int nx,t,w;}e[ME*2+5];
int h[MV+5],en,d[MV+5],q[MV+5],qn,c[MV+5];
int g[MA+5][MB+5],va[MA+5],vb[MB+5],ql[MB+5],qln,qr[MB+5],qrn,s[1<<16];
inline void ins(int x,int y,int w)
{
    e[++en]=(edge){h[x],y,w};h[x]=en;
    e[++en]=(edge){h[y],x,0};h[y]=en;
}
int bfs()
{
    int i,j;
    memset(d,0,sizeof(d));
    for(d[q[i=qn=0]=S]=1;i<=qn;c[q[i]]=h[q[i]],++i)for(j=h[q[i]];j;j=e[j].nx)
        if(e[j].w&&!d[e[j].t])d[q[++qn]=e[j].t]=d[q[i]]+1;
    return d[T];
}
int dfs(int x,int r)
{
    if(x==T)return r;
    int u=0,k;
    for(int&i=c[x];i;i=e[i].nx)if(e[i].w&&d[e[i].t]==d[x]+1)
    {
        k=dfs(e[i].t,r-u<e[i].w?r-u:e[i].w);
        u+=k;e[i].w-=k;e[i^1].w+=k;
        if(u==r)return r;
    }
    return d[x]=0,u;
}
inline int cal(int x){return s[x>>16]+s[x&((1<<16)-1)];}
int dinic()
{
    int i,j,r=0;
    memset(h,0,sizeof(h));en=1;
    for(i=1;i<=qln;++i)ins(S,i,1);
    for(i=1;i<=qrn;++i)ins(i+qln,T,1);
    for(i=1;i<=qln;++i)for(j=1;j<=qrn;++j)
        if(cal(ql[i]|qr[j])%2==0)ins(i,j+qln,INF);
    while(bfs())r+=dfs(S,INF);
    return r;
}
int main()
{
    int t=read(),a,b,m,i,j,k,ans;
    for(i=0;i<16;++i)for(j=1<<i;j<1<<i+1;++j)s[j]=s[j-(1<<i)]+1;
    while(t--)
    {
        a=read();b=read();m=read();
        for(i=1;i<=a;++i)va[i]=read();
        for(i=1;i<=b;++i)vb[i]=read();
        memset(g,0,sizeof(g));
        while(m--)i=read(),g[i][read()]=1;
        for(qln=qrn=0,i=1;i<=b;++i)(vb[i]&1?ql[++qln]:qr[++qrn])=vb[i];
        ans=b-dinic();
        for(i=1;i<=a;++i)
        {
            for(qln=qrn=0,j=1;j<=b;++j)if(g[i][j])
                (vb[j]&1?ql[++qln]:qr[++qrn])=vb[j];
            ans=max(ans,qln+qrn+1-dinic());
        }
        for(i=1;i<=a;++i)for(j=i+1;j<=a;++j)if(va[i]%2!=va[j]%2)
        {
            for(qln=qrn=0,k=1;k<=b;++k)if(g[i][k]&&g[j][k])
                (vb[k]&1?ql[++qln]:qr[++qrn])=vb[k];
            ans=max(ans,qln+qrn+2-dinic());
        }
        printf("%d
",ans);
    }
}

[9018]1667 吴桐学长和网管

题目大意:从1~M中选出N个不同的数,求其倒数和等于X/Y的方案数。(N,M<=50,X,Y<=100,保证方案数不超过10^5)

思路:好像这题正解直接搜索剪枝就过了?我看到这题就想折半搜索,先枚举前M/2,然后Hash存起来,再枚举后M/2算答案,精度有点玄学我手写了个分数类型(不知道会不会爆LL),一开始用的std::map,1秒多才过,我就把题目时限从1s改成2s了哈哈哈,后来手写了个期望O(1)的map,总算卡到1s内。复杂度期望O(2^(M/2))

#include<cstdio>
#define MOD 523333
#define ME 1000000
int gcd(int x,int y){return y?gcd(y,x%y):x;}
struct fs
{
    long long x,y;
    friend bool operator<(fs a,fs b){return a.x*b.y<b.x*a.y;}
    fs operator+(fs b)
    {
        int xx=x*b.y+b.x*y,yy=y*b.y,g=gcd(xx,yy);
        return (fs){xx/g,yy/g};
    }
}f;
struct edge{int nx,t;fs s;}e[ME+5];
int n,ans,en;
inline void ins(int*h,int x,fs s){e[++en]=(edge){h[x],0,s};h[x]=en;}
struct map
{
    int h[MOD];
    int&operator[](fs a)
    {
        int x=((a.x*23333+a.y)%MOD+MOD)%MOD,i;
        for(i=h[x];i;i=e[i].nx)if(e[i].s.x==a.x&&e[i].s.y==a.y)return e[i].t;
        ins(h,x,a);if(en>ME)puts("X");return e[en].t;
    }
}mp[26];
void dfs1(int x,int h,int k,fs s)
{
    if(k>n||f<s)return;
    if(x>h){++mp[k][s];return;}
    dfs1(x+1,h,k,s);dfs1(x+1,h,k+1,s+(fs){1,x});
}
void dfs2(int x,int h,int k,fs s)
{
    if(k>n||f<s)return;
    if(x>h){ans+=mp[n-k][f+(fs){-s.x,s.y}];return;}
    dfs2(x+1,h,k,s);dfs2(x+1,h,k+1,s+(fs){1,x});
}
int main()
{
    int m,x,y;
    scanf("%d%d%d%d",&n,&m,&f.x,&f.y);
    dfs1(1,m>>1,0,(fs){0,1});dfs2((m>>1)+1,m,0,(fs){0,1});
    printf("%d",ans);
}
原文地址:https://www.cnblogs.com/ditoly/p/20170215P.html