2017-10-13 NOIP模拟赛

Posted Soda

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2017-10-13 NOIP模拟赛相关的知识,希望对你有一定的参考价值。

 

入阵曲

 

 

 

 

#include<iostream>
#include<cstdio>
#define maxn 401
#ifdef WIN32
#define PLL "%I64d"
#else
#define PLL "%lld"
#endif
using namespace std;
int n,m,K,a[maxn][maxn],sum[maxn][maxn];
bool flag=1;
long long ans;
int main(){
    //freopen("Cola.txt","r",stdin);
    freopen("rally.in","r",stdin);freopen("rally.out","w",stdout);
    scanf("%d%d%d",&n,&m,&K);
    int w;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            scanf("%d",&a[i][j]);
            sum[i][j]=a[i][j]+sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
            if(i==1&&j==1)w=a[i][j];
            else if(w!=a[i][j])flag=0;
        }
    if(flag){
        for(int i=1;i=n;i++)
        for(int j=1;j<=m;j++)
                if(sum[i][j]%K==0)ans+=1LL*(n-i+1)*(m-j+1);
        printf(PLL,ans);
        return 0;
    }
    for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
        for(int k=i;k<=n;k++)
        for(int l=j;l<=m;l++)
            if((sum[k][l]-sum[i-1][l]-sum[k][j-1]+sum[i-1][j-1])%K==0)ans++;
    printf(PLL,ans);
    return 0;
}
50分 前缀和暴力
#include<iostream>
#include<cstdio>
#define maxn 401
#ifdef WIN32
#define PLL "%I64d"
#else
#define PLL "%lld"
#endif
using namespace std;
int n,m,K,a[maxn][maxn],sum[maxn][maxn];
bool flag=1;
long long ans;
int main(){
    //freopen("Cola.txt","r",stdin);
    freopen("rally10.in","r",stdin);//freopen("rally.out","w",stdout);
    scanf("%d%d%d",&n,&m,&K);
    int w;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            scanf("%d",&a[i][j]);
            sum[i][j]=a[i][j]+sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
            if(i==1&&j==1)w=a[i][j];
            else if(w!=a[i][j])flag=0;
        }
    if(flag){
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
                if(sum[i][j]%K==0)ans+=1LL*(n-i+1)*(m-j+1);
        printf(PLL,ans);
        return 0;
    }
    for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
        for(int k=i;k<=n;k++)
        for(int l=j;l<=m;l++)
            if((sum[k][l]-sum[i-1][l]-sum[k][j-1]+sum[i-1][j-1])%K==0)ans++;
    printf(PLL,ans);
    return 0;
}
65分 前缀和暴力
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define K 1000007
#define N 400
#ifdef WIN32
#define PLL "%I64d"
#else
#define PLL "%lld"
#endif
using namespace std;
int f[K],s[N][N];
int main(){
    freopen("rally.in","r",stdin);freopen("rally.out","w",stdout);
    int n,m,k;
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            scanf("%d",&s[i][j]);
            s[i][j]+=s[i-1][j]+s[i][j-1]-s[i-1][j-1];
            if(s[i][j]<0)s[i][j]+=k;
            if(s[i][j]>0)s[i][j]%=k;
        }
    long long ans=0;
    f[0]=1;
    for(int l=1;l<=m;l++)
        for(int r=l;r<=m;r++){
            for(int i=1;i<=n;i++){
                int sum=s[i][r]-s[i][l-1];
                if(sum<0)sum+=k;
                ans+=f[sum];f[sum]++;
            }
            for(int i=1;i<=n;i++){
                int sum=s[i][r]-s[i][l-1];
                if(sum<0)sum+=k;f[sum]--;
            }
        }
    printf(PLL,ans);
    return 0;
}
100分 压一维

 

将军令

 

#include<iostream>
#include<cstdio>
#define maxn 100010
#define INF 0x7fffffff
using namespace std;
int n,k,t,num,head[maxn],f[maxn][5],dep[maxn],mdep[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;
}
void dfs(int now,int father){
    mdep[now]=dep[now]=dep[father]+1;
    for(int i=head[now];i;i=e[i].pre){
        int to=e[i].to;
        if(to==father)continue;
        dfs(to,now);
        mdep[now]=max(mdep[now],dep[to]);
    }
}
void dfs2(int now,int father){
    int f0=0,f1=0,f2=0;bool fl=0;
    for(int i=head[now];i;i=e[i].pre){
        int to=e[i].to;
        if(to==father)continue;
        fl=1;
        dfs2(to,now);
        f0+=min(f[to][0],min(f[to][1],f[to][2]));
        f1+=f[to][0];
        f2+=f[to][1];
    }
    if(!fl){
        f[now][0]=1;f[now][1]=0,f[now][2]=0;
        return;
    }
    f[now][0]=f0+1;f[now][1]=f1;f[now][2]=max(1,f2);
}
void dfs3(int now,int father){
    int f0=0,f1=0,f2=0,f3=0;bool fl=0;
    for(int i=head[now];i;i=e[i].pre){
        int to=e[i].to;
        if(to==father)continue;
        fl=1;
        dfs3(to,now);
        f0+=min(f[to][0],min(f[to][1],min(f[to][2],f[to][3])));
        f1+=f[to][0];
        f2+=f[to][1];
        f3+=f[to][2];
    }
    if(!fl){
        f[now][0]=1;f[now][1]=0;f[now][2]=0;f[now][3]=0;
        return;
    }
    f[now][0]=f0+1;f[now][1]=f1;f[now][2]=f2;f[now][3]=f3;
    if(mdep[now]-dep[now]>=k)f[now][3]=max(1,f[now][3]);
}
void dfs4(int now,int father){
    int f0=0,f1=0,f2=0,f3=0,f4=0;bool fl=0;
    for(int i=head[now];i;i=e[i].pre){
        int to=e[i].to;
        if(to==father)continue;
        fl=1;
        dfs4(to,now);
        f0+=min(f[to][0],min(f[to][1],min(f[to][2],min(f[to][3],f[to][4]))));
        f1+=f[to][0];
        f2+=f[to][1];
        f3+=f[to][2];
        f4+=f[to][3];
    }
    if(!fl){
        f[now][0]=1;f[now][1]=0;f[now][2]=0;f[now][3]=0;f[now][4]=0;
        return;
    }
    f[now][0]=f0+1;f[now][1]=f1;f[now][2]=f2;f[now][3]=f3;f[now][4]=f4;
    if(mdep[now]-dep[now]>=k)f[now][4]=max(1,f[now][4]);
}
int main(){
    //freopen("Cola.txt","r",stdin);
    freopen("general.in","r",stdin);freopen("general.out","w",stdout);
    scanf("%d%d%d",&n,&k,&t);
    int x,y;
    for(int i=1;i<n;i++){
        scanf("%d%d",&x,&y);
        Insert(x,y);Insert(y,x);
    }
    if(k==0){
        printf("%d",n);
        return 0;
    }
    dfs(1,0);
    if(k==1){
        dfs2(1,0);
        printf("%d",max(1,min(f[1][0],f[1][1])));
        return 0;
    }
    if(k==2){
        dfs3(1,0);
        printf("%d",max(1,min(f[1][0],min(f[1][1],f[1][2]))));
        return 0;
    }
    if(k==3){
        dfs4(1,0);
        printf("%d",max(1,min(f[1][0],min(f[1][1],min(f[1][2],f[1][3])))));
        return 0;
    }
    printf("%d",(n/(k+2)+1));
    return 0;
}
60分 3个树形dp解决部分数据
/*
    贪心 按点的深度排序,每次拿出未被更新的最深的点把他的k级父亲标记
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 100010
using namespace std;
int cut,ans,m,n,K,t,num,head[maxn],fa[maxn],f[maxn],q[maxn];
int Head,Tail;
struct ndoe{
    int from,to,pre;
}e[maxn*2];
void Insert(int from,int to){
    e[++num].from=from;
    e[num].to=to;
    e[num].pre=head[from];
    head[from]=num;
}
void bfs(){
    Head=Tail=1;
    q[Tail++]=1;
    fa[1]=1;
    while(Head<Tail){
        int now=q[Head++];
        for(int i=head[now];i;i=e[i].pre){
            int to=e[i].to;
            if(!fa[to]){
                fa[to]=now;q[Tail++]=to;
            }
        }
    }
}
void update(int now){
    if(!f[now])return;
    for(int i=head[now];i;i=e[i].pre){
        int to=e[i].to;
        if(f[to]<f[now]-1)
            f[to]=f[now]-1,update(to);
    }
}
int main(){
    freopen("general.in","r",stdin);freopen("general.out","w",stdout);
    int x,y;
    scanf("%d%d%d",&n,&K,&t);
    for(int i=1;i<n;i++){
        scanf("%d%d",&x,&y);
        Insert(x,y);Insert(y,x);
    }
    bfs();
    memset(f,-1,sizeof(f));
    for(int i=n;i;i--){
        if(f[q[i]]==-1){
            int j=q[i];
            for(int k=K;k;k--)j=fa[j];
            ans++;f[j]=K;
            update(j);
        }
    }
    printf("%d",ans);
}
100分 贪心

 

星空

 

#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
int s,n,k,m,op[65],opsz[65];
struct node{
    int sta,step;
};
node make_node(int x,int y){
    node res;
    res.sta=x,res.step=y;
    return res;
}
queue<node>q;
bool vis[1<<25];
int main(){
    //freopen("Soda.txt","r",stdin);
    freopen("starlit.in","r",stdin);freopen("starlit.out","w",stdout);
    scanf("%d%d%d",&n,&k,&m);
    s=(1<<n)-1;
    int end=(1<<n)-1;
    int x;
    for(int i=1;i<=k;i++){
        scanf("%d",&x);
        s=s^(1<<(x-1));
    }
    for(int i=1;i<=m;i++){
        scanf("%d",&x);
        op[i]=(1<<x)-1;
        opsz[i]=x;
    }
    vis[s]=1;
    q.push(make_node(s,0));
    while(!q.empty()){
        node cur=q.front();q.pop();
        int stanow=cur.sta;
        for(int i=1;i<=m;i++){
            for(int j=0;j<=n-opsz[i];j++){
                int now=stanow^(op[i]<<j);
                if(now==end){
                    printf("%d",cur.step+1);
                    return 0;
                }
                if(!vis[now]){
                    vis[now]=1;
                    q.push(make_node(now,cur.step+1));
                }
            }
        }
    }
    return 0;
}
24分 前6个点,状态压缩+暴力
#include <bits/stdc++.h>
using namespace std;
 
typedef pair<int, int> pii;
#define fir first
#define sec second
#define INF 0x3f3f3f3f
#define MAXN 40005
#define TOP 18
 
int n, K, m, cnt = 0;
bool a[MAXN];
int dis[18][MAXN], b[70];
pii p[18];
 
queue <int> q;
 
void bfs(pii st)
{
    for (int i = 0; i < MAXN; i++) dis[st.fir][i] = INF;
    q.push(st.sec);
    dis[st.fir][st.sec] = 0;
    while (!q.empty())
    {
        int x = q.front();
        q.pop();
        for (int i = 1; i <= m; i++)
        {
            if (x - b[i] >= 0 && dis[st.fir][x - b[i]] > dis[st.fir][x] + 1)
            {
                dis[st.fir][x - b[i]] = dis[st.fir][x] + 1;
                q.push(x - b[i]);
            }
            if (x + b[i] <= n && dis[st.fir][x + b[i]] > dis[st.fir][x] + 1)
            {
                dis[st.fir][x + b[i]] = dis[st.fir][x] + 1;
                q.push(x + b[i]);
            }
        }
    }
}
 
int dp[1 << 18];
 
int solve(int mask)
{
    if (dp[mask] != -1) return dp[mask];
    if (mask == 0) return 0;
    int &ret = dp[mask];
    ret = INF;
    int x = 0;
    while (!(mask & (1 << x))) x++;
    for (int i = x + 1; i < 2 * K; i++)
        if (mask & (1 << i)) ret = min(ret, solve(mask ^ (1 << x) ^ (1 << i)) + dis[x][p[i].sec]);
    return ret;
}
 
int main()
{
    freopen("starlit.in", "r", stdin);
    freopen("starlit.out", "w", stdout);
    scanf("%d %d %d", &n, &K, &m);
    for (int i = 1, x; i <= K; i++) scanf("%d", &x), a[x] = true;
    for (int i = 1; i <= m; i++) scanf("%d", &b[i]);
    for (int i = 0; i <= n; i++) if (a[i] != a[i + 1]) p[cnt] = pii(cnt, i), cnt++;
    for (int i = 0; i < cnt; i++) bfs(p[i]);
    memset(dp, -1, sizeof dp);
    int ans = solve((1 << cnt) - 1);
    assert(ans != INF);
    printf("%d\\n", ans);
    return 0;
}
100分 std

 

 

 

以上是关于2017-10-13 NOIP模拟赛的主要内容,如果未能解决你的问题,请参考以下文章

个人介绍

noip模拟赛 写代码

NOIp模拟赛binary

NOIP模拟赛16

NOIp模拟赛value

2017 10.25 NOIP模拟赛