BestCoder Round #77

链接:http://bestcoder.hdu.edu.cn/

1001:子集异或和,n=1不为0其他都为0。

代码:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define INF 0x3f3f3f3f
#define Mn 105
#define Mm 200
#define mod 1000000007
#define CLR(a,b) memset((a),(b),sizeof((a)))
#define CPY(a,b) memcpy ((a), (b), sizeof((a)))
#pragma comment(linker, "/STACK:102400000,102400000")
#define ul u<<1
#define ur (u<<1)|1
using namespace std;
typedef long long ll;
int a[1005];
int main() {
    int t;
    scanf("%d",&t);
    while(t--) {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++) {
            scanf("%d",&a[i]);
        }
        if(n==1) cout<<a[1]<<endl;
        else  cout<<0<<endl;
    }
    return 0;
}

1002:求组成的回文串个数。

先判断能否组成回文串,显然奇数个的字符大于1时不能组成回文串,然后组合数求,注意要用逆元或费马小。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define INF 0x3f3f3f3f
#define Mn 10005
#define Mm 200
#define mod 1000000007
#define CLR(a,b) memset((a),(b),sizeof((a)))
#define CPY(a,b) memcpy ((a), (b), sizeof((a)))
#pragma comment(linker, "/STACK:102400000,102400000")
#define ul u<<1
#define ur (u<<1)|1
using namespace std;
typedef long long ll;
int a[1005];
ll fac[1010];
ll ppow(ll k,ll n) {
    ll c=1;
    while(n) {
        if(n%2) c=(c*k)%mod;
        k=(k*k)%mod;
        n>>=1;
    }
    return c;
}
ll C(int a,int b) {
    return (((fac[b]*ppow((fac[a]*fac[b-a])%mod,mod-2)))%mod)%mod;
}
int num[Mn];
int main() {
    int t; fac[0]=1;
    for(int i=1;i<1010;i++) {
        fac[i]=(fac[i-1]*i)%mod;
    }
    scanf("%d",&t);

    while(t--) {
        string s;
        cin>>s;CLR(num,0);
        for(int i=0;i<s.size();i++) {
            num[s[i]-'a']++;
        }
        int flag=0;
        for(int i=0;i<26;i++) {
            if(num[i]%2) flag++;
            num[i]/=2;
        }
        ll ans=1;
        if(flag>1) cout<<0<<endl;
        else {
            int l=s.size()/2;
            for(int i=0;i<26;i++) {
                if(num[i]==0) continue;
                ans=(ans*C(num[i],l))%mod;
                l-=num[i];
            }
            cout<<ans<<endl;
        }
    }
    return 0;
}

1003:

先将所有山峰都加到图里,然后用并查集求出所有连通块,然后从最后一年的山峰开始删,每次判断上下是否连通,连通时答案就是该年。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define INF 0x3f3f3f3f
#define Mn 505
#define Mm 2000005
#define mod 1000000007
#define CLR(a,b) memset((a),(b),sizeof((a)))
#define CPY(a,b) memcpy ((a), (b), sizeof((a)))
#pragma comment(linker, "/STACK:102400000,102400000")
#define ul u<<1
#define ur (u<<1)|1
using namespace std;
typedef long long ll;
int g[Mn*Mn];
int x[Mn*Mn],y[Mn*Mn];
int pre[Mn*Mn];
int n,m;
int way[4][2]={0,-1,-1,0,1,0,0,1};
int find(int x) {
    return x==pre[x]?pre[x]:pre[x]=find(pre[x]);
}
void ol(int x,int y) {
    int a=find(x);
    int b=find(y);
    if(a!=b) pre[a]=b;
}
int main() {
    int t;
    scanf("%d",&t);
    while(t--) {
        string s;
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++) {
            cin>>s;
            for(int j=0;j<m;j++) {
                g[i*m+j]=s[j]-'0';
                pre[i*m+j]=i*m+j;
            }
        }
        int k,ans=0;
        scanf("%d",&k);
        for(int i=1;i<=k;i++) {
            scanf("%d%d",&x[i],&y[i]);
            g[x[i]*m+y[i]]=1;
        }
        int ss=n*m,tt=ss+1;
        pre[ss]=ss;pre[tt]=tt;
        for(int i=0;i<m;i++) if(!g[i])ol(ss,i);
        for(int i=(n-1)*m;i<m*n;i++) if(!g[i])ol(tt,i);
        for(int i=0;i<n;i++) {
            for(int j=0;j<m;j++) {
                //cout<<g[i*m+j];
                if(!g[i*m+j]) {
                    for(int v=0;v<4;v++) {
                        int xx=i+way[v][0];
                        int yy=j+way[v][1];
                        int pos=xx*m+yy;
                        if(yy<0||yy>=m||xx<0||xx>=n||g[pos]) continue;
                        ol(i*m+j,pos);
                    }
                }
            }
        }
        if(find(ss)==find(tt)) {
            cout<<-1<<endl;
            continue;
        }
        for(int i=k;i>=1;i--) {
            g[x[i]*m+y[i]]=0;
            if(x[i]==0) ol(ss,x[i]*m+y[i]);
            else if(x[i]==n-1) ol(tt,x[i]*m+y[i]);
            for(int v=0;v<4;v++) {
                int xx=x[i]+way[v][0];
                int yy=y[i]+way[v][1];
                int pos=xx*m+yy;
                if(yy<0||yy>=m||xx<0||xx>=n||g[pos]) continue;
                ol(x[i]*m+y[i],pos);
            }
            if(find(ss)==find(tt)) {
                ans=i;
                break;
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}

1004:

每次更新dp[i]时,遍历i可以炸的范围。
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define INF 0x3f3f3f3f
#define Mn 2010
#define Mm 2000005
#define mod 1000000007
#define CLR(a,b) memset((a),(b),sizeof((a)))
#define CPY(a,b) memcpy ((a), (b), sizeof((a)))
#pragma comment(linker, "/STACK:102400000,102400000")
#define ul u<<1
#define ur (u<<1)|1
using namespace std;
typedef long long ll;
int a[Mn];
double dp[Mn];
int main() {
    int t,n,m,x;
    scanf("%d",&t);
    while(t--) {
        scanf("%d%d",&n,&m);
        CLR(a,0);
        for(int i=1;i<=m;i++) {
            scanf("%d",&x);
            a[x+1]=1;
        }
        CLR(dp,0);
        for(int i=1;i<=n;i++) {
            int flag=0;
            for(int j=i;j>0;j--) {
                if(a[j]) flag++;
                if(flag>1) break;
                if(flag==1) dp[i]=max(dp[i],dp[j-1]+log2(i-j+1));
            }
        }
        printf("%.0f\n",floor(1000000.0*dp[n]));
    }
    return 0;
}


1005:

首先将数列中所有满足条件的三元组处理出来。 设 pre[i] 为第 i 个三元组前一次出现的位置,如果在前面没有出现过则设为1,对于不合法的三元组,

pre[i]设为 n。 这样对于一个查询 [L, R], 我们只需要计算出 在这个区间内有多少个三元组的 pre 值是小于 L 的。 到这里,就可以使用可持久化线段树来计算了。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define INF 0x3f3f3f3f
#define Mn 200005
#define Mm 4000005
#define mod 1000000007
#define CLR(a,b) memset((a),(b),sizeof((a)))
#define CPY(a,b) memcpy ((a), (b), sizeof((a)))
#pragma comment(linker, "/STACK:102400000,102400000")
#define ul u<<1
#define ur (u<<1)|1
using namespace std;
typedef long long ll;
struct node {
    int x,y,z,w;
    node(){}
    node(int x,int y,int z,int w):x(x),y(y),z(z),w(w){}
}p[Mn];
bool cmp(node a,node b) {
    if(a.x!=b.x) return a.x<b.x;
    if(a.y!=b.y) return a.y<b.y;
    if(a.z!=b.z) return a.z<b.z;
    return a.w<b.w;
}
int tot=0;
int root[Mn],ls[Mm],rs[Mm],sum[Mm];
void Insert(int l,int r,int x,int &y,int val) {
    y=++tot;
    sum[y]=sum[x]+1;
    if(l==r) return ;
    ls[y]=ls[x],rs[y]=rs[x];
    int mid=(l+r)>>1;
    if(val<=mid) Insert(l,mid,ls[x],ls[y],val);
    else Insert(mid+1,r,rs[x],rs[y],val);
}
int ask(int l,int r,int x,int y,int k) {
    if(l==r) return sum[y]-sum[x];
    int mid=(l+r)>>1;
    if(mid>=k) return ask(l,mid,ls[x],ls[y],k);
    else return sum[ls[y]]-sum[ls[x]]+ask(mid+1,r,rs[x],rs[y],k);
}
int fl[Mn];
int pre[Mn];
int b[Mn];
int a[Mn];
int main() {
    int t;scanf("%d",&t);
    while(t--) {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        for(int i=1;i<=n-2;i++) p[i]=node(a[i],a[i+1],a[i+2],i);
        sort(p+1,p+n-1,cmp);
        p[0].x=p[0].y=p[0].z=p[0].w=-1;
        int cnt=0;
        for(int i=1;i<=n-2;i++) {
            if(p[i].x<=p[i].y&&p[i].y<=p[i].z) {
                if(p[i].x!=p[i-1].x||p[i].y!=p[i-1].y||p[i].z!=p[i-1].z) fl[p[i].w]=++cnt;
                else fl[p[i].w]=cnt;
            } else fl[p[i].w]=0;
        }
        CLR(b,0);
        sum[0]=root[0]=ls[0]=rs[0]=tot=0;
        for(int i=1;i<=n-2;i++) {
            if(!fl[i]) pre[i]=n;
            else pre[i]=b[fl[i]]+1;b[fl[i]]=i;
            Insert(1,n,root[i-1],root[i],pre[i]);
        }
        int m;
        scanf("%d",&m);
        while(m--) {
            int l,r;
            scanf("%d%d",&l,&r);
            if(r-l<2) printf("0\n");
            else printf("%d\n",ask(1,n,root[l-1],root[r-2],l));
        }
    }
    return 0;
}



你可能感兴趣的:(BestCoder Round #77)