2017.07.16【NOIP提高组】模拟赛B组 卫星照片 题解

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2017.07.16【NOIP提高组】模拟赛B组 卫星照片 题解相关的知识,希望对你有一定的参考价值。

参考技术A https://jzoj.net/senior/#contest/show/2062/0

农夫 John 正在研究他的农场的卫星照片.照片为一个R (1 <=R <= 75) 行 C (1 <= C <= 75) 列的字符矩阵表示.如下图:

图上的一块相连通的 "#" 表示一群奶牛或一个房间, 两个子"#" 连通的意思是说左右或上下相连.而下面的两块则是分开的:

John现在根据卫星照片上的的这些"#"块的形状来判断哪些是牛群,哪些是房间.如果一个"#"块形状一个内部和边全部都是“#”的矩形,则是房间,如果一个连通块只有一个“#”,也是房间.其它的则认为都是牛群.在第一个图中,有三个房间 ( 2x1, 2x5, and 1x1)和2群牛.
请根据输入文件中的数据,统计出房间数和牛群数.数据中牛群不会包围另一个牛群或房间.

2
2

爆搜,找到每一个‘#’块,判断它是不是矩阵即可

2017.12.09NOIP提高组模拟赛A组

2017.12.09【NOIP提高组】模拟赛A组

T1 3489. 【NOIP2013模拟联考11】数列的GCD(gcd)
T2 3500.【NOIP2013模拟联考15】物语(monogatari)
T3 3501.【NOIP2013模拟联考15】消息传递(news)

吐槽:这次的题好像有点水啊,但最简单的第二题都给打挂啦!!(数组开小了)

T1

本套题中最难的题。考虑dp
设f[i]是b[1],b[2]...b[N]的最大公约数的数目,g[i]是b[1],b[2]...b[N]的公约数的数目。
则显然有\(g[i]=\sum_{d|i}f[d]\)
g[i]十分好求。

设l[i]为{a[N]}中满足 i|a[j] (1<=j<=N)的数目

\[g[d]={l[d] \choose n-k}\lfloor\frac{m}{d}\rfloor^{n-l[d]}(\lfloor\frac{m}{d}\rfloor-1)^{l[d]-n+k}\]

Code

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define rep(i,x) for(int i=head[x];i;i=next[i])
#define mem(a,x) memset(a,x,sizeof(a))
typedef long long LL;
typedef double DB;
using namespace std;
inline int read() {
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9') f=(ch=='-')?-1:f,ch=getchar();
    while(ch>='0'&&ch<='9') x=x*10+(ch-'0'),ch=getchar();return f*x;
}
const int n=300010,mo=1e9+7;
int a[n],cnt[n],ji[n];
LL fac[n],ans[n];
LL qpow(LL a,int b) {
    a=a%mo;
    LL ans=1;
    for(;b;a=(a*a)%mo,b>>=1) if(b&1) ans=(ans*a)%mo;
    return ans;
}
LL C(int m,int n) {return fac[n]*qpow(fac[m],mo-2)%mo*qpow(fac[n-m],mo-2)%mo;}
int main() {
    int n=read(),m=read(),k=read();
    k=n-k;
    fo(i,1,n) a[i]=read(),ji[a[i]]++;
    fd(i,m,1) for(int j=i;j<=m;j+=i) cnt[i]=cnt[i]+ji[j];
    fac[0]=1;
    fo(i,1,n) fac[i]=((LL)fac[i-1]*i)%mo;
    fd(i,m,1) {
        if(cnt[i]<k) ans[i]=0;
        else {
            ans[i]=C(k,cnt[i])*qpow(m/i-1,cnt[i]-k)%mo*qpow(m/i,n-cnt[i])%mo;
            fo(j,2,m/i) ans[i]=(ans[i]+mo-ans[i*j])%mo;
        }
    }
    fo(i,1,m) printf("%lld ",ans[i]);
    return 0;
}

T2

最简单的题。

只用考虑经不经过这个点即可,经过可分为两种情况:
技术分享图片
将就着看一下吧,正反做一遍dij就行了。

Code

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
#define pr pair<LL, int>
#define mp make_pair
#define x first
#define y second
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define rep(i,x) for(int i=head[x];i;i=g[i].next)
#define mem(a,x) memset(a,x,sizeof(a))
typedef long long LL;
typedef double DB;
using namespace std;
inline int read() {
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9') f=(ch=='-')?-1:f,ch=getchar();
    while(ch>='0'&&ch<='9') x=x*10+(ch-'0'),ch=getchar();return f*x;
}
const LL INF=0x7ffffffffffff;
const int N=5e5+50,M=5e5+50;
struct Edge {int x,next;LL dis;} g[M*2] ;
int n,m,k,begin,end,tx,ty,ww;
LL G[N],F[N];
int head[N],w,vis[N];
priority_queue<pr>q;
void add(int x,int y,LL dis) {g[++w].x=y,g[w].next=head[x],g[w].dis=dis,head[x]=w;}
void dij(int x) {
    int tmp;
    LL now;
    fo(i,1,n) F[i]=INF;
    F[x]=0,q.push(mp(0,x));
    while(!q.empty()) {
        x=q.top().y;
        LL now=q.top().x;q.pop();
        if(-now>F[x]) continue;
        now=-now;
        rep(i,x) if(F[tmp=g[i].x]>F[x]+g[i].dis) F[tmp]=F[x]+g[i].dis,q.push(mp(-F[tmp],tmp));
    }
}
int main() {
//  freopen("2.in","r",stdin);
    freopen("monogatari.in","r",stdin),freopen("monogatari.out","w",stdout);
    n=read(),m=read(),k=read();
    fo(i,1,m-1) {tx=read(),ty=read(),scanf("%lld",&ww),add(tx,ty,ww),add(ty,tx,ww);}
    scanf("%d%d",&begin,&end);
    dij(1);
    memcpy(G,F,sizeof(G));
    dij(n);
    fo(i,1,k) {
        scanf("%lld",&ww);
        LL tmp=min(G[n],min(G[begin]+F[end],G[end]+F[begin])+ww);
        if(tmp==INF) printf("+Inf\n") ;
        else printf("%lld\n",tmp) ;
    }
}

T3

考虑树形dp,明显要旋根,记录每个点儿子的前缀和后缀最大值。
随便搞一下就行了。(很简单,相出dp就行了)

Code

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define rep(i,x) for(int i=head[x];i;i=next[i])
#define mem(a,x) memset(a,x,sizeof(a))
typedef long long LL;
typedef double DB;
using namespace std;
inline int read() {
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9') f=(ch=='-')?-1:f,ch=getchar();
    while(ch>='0'&&ch<='9') x=x*10+(ch-'0'),ch=getchar();return f*x;
}
const int mn=401000;
int n,tt=1,fa[mn],head[mn],next[mn*2],to[mn*2];
int f[mn],g[mn],sum[mn],ans[mn],u[mn],q[mn],cnt=0;
int pre[mn],sa[mn],tot;
void add(int i,int j) {next[++tot]=head[i],head[i]=tot,to[tot]=j;}
bool cmp(int i,int j) {return sum[i]<sum[j];}
void solve() {
    int a=1,b=1;
    q[1]=1;
    while(a<=b) {
        int now=q[a++];
        rep(p,now) if(to[p]!=fa[now]) q[++b]=to[p];
    }
    fd(i,n,1) {
        int now=q[i],tt=0;
        rep(p,now) if(to[p]!=fa[now]) u[++tt]=f[to[p]];
        sort(u+1,u+1+tt);
        fo(j,1,tt) f[now]=max(f[now],u[j]+tt-j+1);
    }
    ans[1]=f[1];
    fo(i,1,n) {
        int now=q[i],tt=0;
        rep(p,now) if(to[p]!=fa[now]) u[++tt]=to[p],sum[to[p]]=f[to[p]];
        if(now!=1) u[++tt]=fa[now],sum[fa[now]]=g[now];
        sort(u+1,u+1+tt,cmp);
        pre[0]=sa[tt+1]=0;
        fo(j,1,tt) ans[now]=max(ans[now],sum[u[j]]+tt-j+1);
        fo(j,1,tt) pre[j]=max(pre[j-1],sum[u[j]]+tt-j);
        fd(j,tt,1) sa[j]=max(sa[j+1],sum[u[j]]+tt-j+1);
        fo(j,1,tt) if(u[j]!=fa[now]) g[u[j]]=max(pre[j-1],sa[j+1]);
    }
}
int main() {
    freopen("news.in","r",stdin),freopen("news.out","w",stdout);
    n=read();
    fo(i,2,n) fa[i]=read(),add(fa[i],i),add(i,fa[i]);
    int tmp=1<<30;
    solve();
    fo(i,1,n) tmp=min(tmp,ans[i]);
    printf("%d\n",tmp+1);
    fo(i,1,n) if(ans[i]==tmp) printf("%d ",i);
    bool first=1;
    return 0;
}

以上是关于2017.07.16【NOIP提高组】模拟赛B组 卫星照片 题解的主要内容,如果未能解决你的问题,请参考以下文章

2017.07.14NOIP提高组模拟赛B组

2017.07.09NOIP提高组模拟赛B组

2017.08.05NOIP提高组模拟赛B组

2017.08.06NOIP提高组模拟赛B组

2017.07.07NOIP提高组模拟赛B组

2017.07.11NOIP提高组模拟赛B组