清北刷题冲刺 11-01 p.m

轮换

 

#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 1010
using namespace std;
int n,p,k,a[maxn],b[maxn],op[maxn][maxn],pos[maxn];
int main(){
    freopen("rotate.in","r",stdin);freopen("rotate.out","w",stdout);
//    freopen("Cola.txt","r",stdin);
    scanf("%d%d%d",&n,&p,&k);
    for(int i=1;i<=n;i++)a[i]=i,b[i]=i;
    for(int i=1;i<=p;i++){
        scanf("%d",&op[i][0]);
        for(int j=1;j<=op[i][0];j++)
            scanf("%d",&op[i][j]);
    }
    for(int i=p;i>=1;i--){
        for(int j=1;j<=op[i][0];j++){
            pos[j]=b[op[i][j]];
        }
        int w=op[i][1];
        for(int j=1;j<=op[i][0];j++){
            int x=op[i][j],y=op[i][j+1];
            if(j==op[i][0])y=w;
            a[pos[j]]=y;
            b[y]=pos[j];
        }
    }
    for(int i=1;i<=n;i++)printf("%d ",a[i]);
    return 0;
}
100分 模拟

 

 

 

区间

 

#include<iostream>
#include<cstdio>
#define mod 1000000007
using namespace std;
int val[1000010];
int sum[1000010];
int n,a,b,c,d,ans,q,w,e;
int qread(){
    int i=0;
    char ch=getchar();
    while(ch<'0'||ch>'9') ch=getchar();
    while(ch<='9'&&ch>='0'){i=i*10+ch-'0';ch=getchar();}
    return i;
}
int main(){
    freopen("range.in","r",stdin);freopen("range.out","w",stdout);
    n=qread(),a=qread(),b=qread(),c=qread(),d=qread();
    for(int i=1;i<=n;i++){
        val[i]=qread();
        if(val[i]>=a&&val[i]<=b&&val[i]>=c&&val[i]<=d) ans++;
    }
    for(int i=1;i<=n;i++){
        w=e=val[i];
        for(int j=i+1;j<=n;j++){
            w=w&val[j];e=e|val[j];
            if(w<a||e>d) break;
            if(w<=b&&e>=c) ans++;
        }
        while(ans>mod) ans-=mod;
    }
    cout<<ans;
}
60分 暴力
/*
3 2 2 3 3
2 3 3
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define mod 1000000007
#define maxn 100005
long long cnt;
int s[maxn],n,a,b,c,d,sta[maxn][20],sto[maxn][20];
using namespace std;
int aska(int l,int r){
    int L=r-l+1;
    int t=log2(L);
    return sta[l][t]&sta[r-(1<<t)+1][t];
}
int asko(int l,int r){
    int L=r-l+1;
    int t=log2(L);
    return sto[l][t]|sto[r-(1<<t)+1][t];
}
int main(){
    freopen("range7.in","r",stdin);
    scanf("%d%d%d%d%d",&n,&a,&b,&c,&d);
    for(int i=1;i<=n;i++){
        scanf("%d",&s[i]);
        sta[i][0]=sto[i][0]=s[i];
    }
    for(int j=1;j<20;j++)
        for(int i=1;i<=n;i++)
            if(i+(1<<j)-1<=n){
                sta[i][j]=sta[i][j-1]&sta[i+(1<<j-1)][j-1];
                sto[i][j]=sto[i][j-1]|sto[i+(1<<j-1)][j-1];
            }
    for(int i=1;i<=n;i++){
        int andsum=s[i],orsum=s[i];
        for(int j=i;j<=n;j++){
            int L=j,R=n+1;//二分右端点 
            andsum=aska(i,j);
            orsum=asko(i,j);
            while(R-L>1){
                int mid=(L+R)>>1;
                if(aska(i,mid)==andsum&&asko(i,mid)==orsum)L=mid;
                else R=mid;
            }
            if(a<=andsum&&andsum<=b&&c<=orsum&&orsum<=d){
                cnt+=L-j+1;
            }
            j=L;
        }
    }
    cout<<cnt%mod<<endl;
}
100分 枚举左端点+二分右端点+st表维护区间信息

 

 

收集果子

 

#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 1010
using namespace std;
int w[maxn],ans,fa[maxn],sz[maxn],n,k;
struct node{
    int from,to;
}E[maxn];
int find(int x){
    if(x==fa[x])return x;
    return fa[x]=find(fa[x]);
}
void connect(int x,int y){
    int f1=find(x),f2=find(y);
    if(f1==f2)return;
    fa[f2]=f1;
    sz[f1]+=sz[f2];
    sz[f2]=0;
}
int main(){
    freopen("fruit.in","r",stdin);freopen("fruit.out","w",stdout);
//    freopen("Cola.txt","r",stdin);
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++)scanf("%d",&w[i]);
    for(int i=1;i<n;i++)scanf("%d%d",&E[i].from,&E[i].to);
    int all=(1<<(n-1));
    for(int i=0;i<all;i++){
        for(int j=1;j<=n;j++)fa[j]=j,sz[j]=w[j];
        int now=i,pos=0;
        while(now){
            pos++;
            if(now&1){
                connect(E[pos].from,E[pos].to);
            }
            now>>=1;
        }
        if(sz[find(1)]==k)ans++;
    }
    cout<<ans;
    return 0;
}
30分 暴力
/*
    从根节点向下递归求方案数,回溯的时候将叶子儿子节点方案数累加到根节点上
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define mod 1000000007
#define maxn 1005
using namespace std;
int n,k,a[maxn],num,head[maxn];
long long pw2[maxn],dp[maxn][maxn];
struct node{int to,pre;}e[maxn*2];
void Insert(int from,int to){
    e[++num].to=to;
    e[num].pre=head[from];
    head[from]=num;
}
int dfs(int now,int father){
    int sz=1;
    for(int i=head[now];i;i=e[i].pre){
        int to=e[i].to;
        if(to==father)continue;
        for(int j=0;j<=n-a[to];j++)
            dp[to][j+a[to]]=dp[now][j];
        int tmp=dfs(to,now);
        for(int j=0;j<=n;j++)
            dp[now][j]=(pw2[tmp-1]*dp[now][j]%mod+dp[to][j])%mod;
        sz+=tmp;
    }
    return sz;
}
int main(){
    freopen("fruit.in","r",stdin);
    scanf("%d%d",&n,&k);
    pw2[0]=1;
    for(int i=1;i<=n;i++)pw2[i]=pw2[i-1]*2%mod;
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    for(int i=1,x,y;i<n;i++){
        scanf("%d%d",&x,&y);
        Insert(x,y);Insert(x,y);
    }
    dp[1][a[1]]=1;
    dfs(1,0);
    cout<<dp[1][k];
    return 0;
}
100分 树形dp

 

 

 

 

预计得分100+30+20
实际得分100+60+30
T1一开始题意没懂,写完T2T3再看的,T1就是一个模拟,比较锻炼读题能力。T2看到位运算觉得有点蒙蔽,就直接暴力了,T3前30%的数据可以状态压缩搞一搞,写完发现最劣的情况是2^20*20,复杂度有可能过不去
今天状态不好,没集中精力做题,要培养善于调整的精神状态,积极投入考试
小结

 

posted @ 2017-11-01 16:34  Echo宝贝儿  阅读(217)  评论(0编辑  收藏  举报