zoukankan      html  css  js  c++  java
  • 2017.12.09【NOIP提高组】模拟赛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}lfloorfrac{m}{d} floor^{n-l[d]}(lfloorfrac{m}{d} floor-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
    ") ;
    		else printf("%lld
    ",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
    ",tmp+1);
    	fo(i,1,n) if(ans[i]==tmp) printf("%d ",i);
    	bool first=1;
    	return 0;
    }
    
  • 相关阅读:
    phpcms后台获取当前登录账号的数据
    【原生】验证码的生成
    PHP 生成图片缩略图函数
    3秒后自动跳转页面【js】
    JS定时器
    JS字符串转换成json对象。。。。
    JVM调优总结(十二)-参考资料
    JVM调优总结(十一)-反思
    JVM调优总结(十)-调优方法
    浅谈java内存泄漏
  • 原文地址:https://www.cnblogs.com/patricksu/p/8011699.html
Copyright © 2011-2022 走看看