9.25+9.27 联考

Day 1
第一次和某二中学联考,达哥出题,翻车十分惨烈
考试时上来10分钟搞定T1,看T2,没思路,二维莫队?好像和图论有点关系,有点乱,先弃坑,看T3,发现只需要处理前a个,后面都是等差数列,但是需要记录一大堆东西,手玩了一下,发现有戏,搞出来,发现只能过前两个点,后面的起点都不在a内,特判,乱搞了好长时间,最后5个样例都过了,但是时间只剩下30min左右了,觉得可能还有别的情况,但弃了,搞T2,把20分的暴力打出来基本就没时间了,急忙交了。
T2,发现20分的暴力好像能过70分。。。但是我只在q==1时才运行。QAQ……正解利用了连通块数目=点数-边数,直接二维前缀和搞定。。。。
T3发现是预处理的一个细节打挂了,还有一个等号放错了,挂了30
应该100+70+100实际却是100+20+70=190。
T1

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#define N 17
#define LL long long
using namespace std;
int bit[20],n;
bool vis[N][66666];
LL a[N],b[N],c[N],d[N];
LL ans,f[N][66666],g[N][66666];
int main(){
    bit[0]=1;for(int i=1;i<=17;i++)bit[i]=bit[i-1]<<1;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%lld%lld%lld%lld",&a[i],&b[i],&c[i],&d[i]);
    vis[0][0]=1;
    for(int i=1;i<=n;i++){
        for(int j=0;j<bit[n];j++){
            if(vis[i-1][j]){
                f[i][j|bit[i-1]]=f[i-1][j]+a[i];
                g[i][j|bit[i-1]]=max((LL)0,g[i-1][j]-b[i]);
                g[i][j]=g[i-1][j]+c[i];
                f[i][j]=max((LL)0,f[i-1][j]-d[i]);
                vis[i][j]=vis[i][j|bit[i-1]]=1;
            }
        }
    }
    for(int i=0;i<bit[n];i++)
        ans=max(ans,f[n][i]*g[n][i]);
    printf("%lld\n",ans);
    return 0;
}

T2

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#define N 2005
using namespace std;
int n,m,q;
char ch[N][N];
int a[N][N],g[N][N],h[N][N];
int qq(int a[N][N],int x,int y,int x2,int y2){
    return a[x2][y2]-a[x2][y-1]-a[x-1][y2]+a[x-1][y-1];
}
int query(int x,int y,int x2,int y2){
    return qq(a,x,y,x2,y2)-qq(g,x,y+1,x2,y2)-qq(h,x+1,y,x2,y2);
}
int main(){
    scanf("%d%d%d",&n,&m,&q);
    for(int i=1;i<=n;i++){
        scanf("%s",ch[i]);
        for(int j=1;j<=m;j++)
            a[i][j]=ch[i][j-1]-'0';
    }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(a[i][j]){
                if(a[i][j-1])g[i][j]++;
                if(a[i-1][j])h[i][j]++;
            }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {a[i][j]+=a[i][j-1];g[i][j]+=g[i][j-1];h[i][j]+=h[i][j-1];}
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {a[i][j]+=a[i-1][j];g[i][j]+=g[i-1][j];h[i][j]+=h[i-1][j];}
    int x,y,x2,y2;
    while(q--){
        scanf("%d%d%d%d",&x,&y,&x2,&y2);
        printf("%d\n",query(x,y,x2,y2));
    }
    return 0;
}

T3

#pragma GCC optimize ("O3")
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#define N 200005
#define int long long
using namespace std;
int nxt[N],sum[N],c[N],t[N];
int n,a,x,mod;
void add(int x){for(;x<=a;x+=(x&-x))c[x]++;}
int query(int x){
    int ans=0;
    for(;x;x-=(x&-x))ans+=c[x];
    return ans;
}
signed main(){
    scanf("%lld%lld%lld%lld",&n,&x,&a,&mod);
    for(int i=1,now=x,last=0,tim=0;i<=n;i++){
        if(now<a){
            nxt[last]=now+1;
            sum[now+1]=sum[last]+tim;
            t[last]=tim;last=now+1;tim=0;
        }
        else tim++;
        if(i==n){t[last]=tim;}
        now=(now+a)%mod;
    }
    int now=nxt[0],qian,hou,num=0,ans=0,ans1;
    int when=0,be=x;
    if(a<=x){while(be>=a)be-=a,when++;}
    now=nxt[0]; num=0; ans=0;
    while(now){
        qian=query(now);
        hou=num-qian;
        add(now);
        ans+=hou; ans+=sum[now];
        ans+=t[now]*(sum[now]-qian)-(t[now]*(t[now]-1)*num)/2;
        if(a<=x){
            if(now>be)ans-=(t[now]+1-when)*(t[now]+1-when+1)/2;
            else ans-=(t[now]+1-when)*(t[now]+1-when-1)/2;
        }
        now=nxt[now];
        num++;
    }
    printf("%lld\n",ans);
    return 0;
}

老子不服!

Day 2
T1 用一个有明显错误的暴力乱搞了95
正解枚举起点;
d=x/y=p1q1...pkqk
g=gcd(q1...qk)
最小公比就是p1q1/g...pkqk/g
还要map判重
T2 树上的概率dp 考试时特判还挂了,正解枚举重儿子,f[i][j]表示i的子树内最长链为j的概率,轻重儿子分别转移就好了。
T3 题目大意是说求去掉或添加某一条边能使原图变成一个联通的欧拉图的方案数
ans=×C2n
所以就是要求联通的欧拉图路径,设不一定联通的欧拉图方案数为g[i],满足联通的为f[i];
g[i]=2C2i1为什么呢,因为我们任选出一个点作为补偿点,其余的i-1个点任意连边都可以通过这个补偿点使图满足是不一定联通的欧拉图。
f[i]=g[i]i1j=1f[j]g[ij]Cj1i1
减去的为什么是不合法的呢
还是任选一个点,因为这个图不满足联通,所以这个点所在的联通块大小一定在1~i-1范围内,再从剩下的i-1个点中任选j-1个点与其组成联通块,这个块满足联通,而剩下的不一定,但这两部分间一定不联通,所以就是上式
T1

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<map>
#define N 100002
#define LL long long
using namespace std;

map<LL,int> mm;

int n,ans=1,f[N];
LL a[N],b[N],x,y,z;
LL gcd(LL a,LL b){return b==0?a:gcd(b,a%b);}

LL tot,prime[500],tim[500],gg;
void work(LL &x){
    tot=0; gg=0;
    for(int i=2;i*i<=x;i++){
        if(i>1000){x=0;return;}
        if(x%i==0){
            prime[++tot]=i;tim[tot]=0;
            while(x%i==0){tim[tot]++;x/=i;}
            gg=gcd(gg,tim[tot]);
        }
    }
    for(int i=1;i<=tot;i++)
        x*=pow(prime[i],tim[i]/gg);
}

bool check(LL x,LL y){
    LL xx=x;
    while(xx<y) xx*=x;
    return xx==y;
}

LL read(){
    LL a=0;char ch=getchar();
    while(ch<'0'||ch>'9')ch=getchar();
    while(ch>='0'&&ch<='9'){a=a*10+(ch^48);ch=getchar();}
    return a;
}
int main(){
    scanf("%d",&n); ans=1;
    for(int i=1;i<=n;i++)
        a[i]=read();
    for(int i=2;i<=n;i++)
        if(a[i]==a[i-1])f[i]=f[i-1]+1,ans=max(ans,f[i]+1);
    if(ans>=64){printf("%d\n",ans);return 0;}
    for(int i=1,j,num;i<n;i++){
        x=max(a[i],a[i+1]);
        y=min(a[i],a[i+1]);
        if(x%y!=0)continue;
        z=x/y;   work(z);
        if(z<=1)continue;
        num=0; ans=max(ans,2);
        mm.clear();mm[x]=++num;mm[y]=++num;
        for(j=i+2;j<=n;j++){
            x=max(a[j],a[j-1]);
            y=min(a[j],a[j-1]);
            if(x%y!=0)break;
            if(!check(z,x/y))break;
            if(mm[a[j]])break; mm[a[j]]=++num;
            ans=max(ans,j-i+1);
        }if(j==n+1)break;
    }
    printf("%d\n",ans);
    return 0;
}

T2

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>
#define N 3050
#define LL long long
#define mod 1000000007
using namespace std;
int n,m;
int son[N][N],dep[N],num[N];
bool vis[N];
LL ny(LL a){
    LL ans=1;LL b=mod-2;
    while(b){
        if(b&1)ans=(ans*a)%mod;
        a=(a*a)%mod; b>>=1;
    }
    return ans;
}
LL f[N][N],s[N][N],tmp[N];
void dfs(int x){
    if(!num[x]){
        f[x][0]=s[x][0]=1;
        return;
    }
    for(int i=1;i<=num[x];i++){
        dfs(son[x][i]);
        dep[x]=max(dep[x],dep[son[x][i]]+1);
    }
    LL mom=ny(num[x]),S;
    //printf("x===========%d  %lld\n",x,mom);
    for(int i=1;i<=num[x];i++){
        memset(tmp,0,sizeof tmp);
        tmp[0]=1;
        int u=son[x][i];
        for(int j=1,k;j<=num[x];j++){
            int v=son[x][j];
            //printf("u===%d  v===%d\n",u,v);
            if(u==v){
                for(S=0,k=0;k<=dep[v];k++){
                    S=(S+tmp[k])%mod;
                    //printf("before-----%lld\n",tmp[k]);
                    tmp[k]=((S*f[v][k]%mod+tmp[k]*s[v][k]%mod-tmp[k]*f[v][k]%mod)+mod)%mod;
                    //printf("after------%lld\n",tmp[k]);
                }
            }
            else{
                for(S=tmp[0],k=0,tmp[0]=0;k<=dep[v];k++){
                    S=(S+tmp[k+1])%mod;
                    tmp[k+1]=((S*f[v][k]%mod+tmp[k+1]*s[v][k]%mod-tmp[k+1]*f[v][k]%mod)+mod)%mod;
                }
            }
        }
        for(int j=0;j<=dep[x];j++)
            f[x][j]=(f[x][j]+(tmp[j]*mom)%mod)%mod;
    }
    s[x][0]=f[x][0];
    for(int i=1;i<=dep[x];i++)s[x][i]=(s[x][i-1]+f[x][i])%mod;
}
void print(int x){
    LL ans=0;
    for(int i=0;i<=dep[x];i++)
        ans=(ans+(i*f[x][i])%mod)%mod;
    printf("%lld\n",ans);
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&num[i]);
        for(int j=1;j<=num[i];j++){
            scanf("%d",&son[i][j]);
            vis[son[i][j]]=1;
        }
    }
    for(int i=1;i<=n;i++)
        if(!vis[i]){
            dfs(i);
            print(i);
            //for(int j=1;j<=n;j++)print(j);
            return 0;
        }
}

T3

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 2005
#define mod 1000000007
#define LL long long
using namespace std;
LL c[N][N],f[N],g[N],n;
LL qp(LL a,LL b){
    LL ans=1;
    while(b){
        if(b&1)ans=(ans*a)%mod;
        a=(a*a)%mod; b>>=1;
    }return ans;
}
int main(){
    scanf("%lld",&n);
    f[1]=g[1]=1;
    for(int i=0;i<=n;i++){
        c[i][0]=1;
        for(int j=1;j<=i;j++)
            c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
    }
    for(int i=2;i<=n;i++){
        g[i]=qp(2,c[i-1][2]);
        for(int j=1;j<i;j++)
            (f[i]+=f[j]*g[i-j]%mod*c[i-1][j-1]%mod+mod)%=mod;
        f[i]=(g[i]-f[i]+mod)%mod;
    }
    printf("%lld\n",f[n]*c[n][2]%mod);
}
posted @ 2017-09-26 09:42  Ren_Ivan  阅读(144)  评论(0编辑  收藏  举报