zoukankan      html  css  js  c++  java
  • P2351 [SDOI2012]吊灯

    洛谷 p2351 [SDOI2012]吊灯

    题目分析

    题目链接

    看完这个题后,我们可以得出一个很显然的结论,要保证一颗节点数为n的树可以分成若干个大小

    为i的连通块,一定有i | n且定有n/i个节点的子树节点数之和(包括其本身)是i的倍数,(很显然,但
    不会证
    )

    所以思路就很简单了,统计每个点的子节点个数,然后进行判断就行了

    最开始统计个数用了dfs(本题这么明显的优化提示没注意) 期望得分70,但统计倍数个数的时候时

    间复杂度炸了,被卡到40。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    using namespace std;
    const int maxn=2e6+10;
    inline int read(){
    	int ret=0;
    	int f=1;
    	char ch=getchar();
    	while(ch<'0'||ch>'9'){
    		if(ch=='-')
    			f=-f;
    		ch=getchar();
    	}
    	while(ch<='9'&&ch>='0'){
    		ret=ret*10+(ch^'0');
    		ch=getchar();
    	}
    	return f*ret;
    }
    int num[maxn];
    int n;
    int size[maxn];
    int f[maxn];
    int main(){
    	freopen("a.in","r",stdin);
    	n=read();
    	int t=10;
    	while(t--){
    		for(int i=2;i<=n;i++){
    			if(t==9){
    				f[i]=read();
    			}
    			else{
    				f[i]=(f[i]+19940105)%(i-1)+1;
    			}	
    		}
    		memset(num,0,sizeof(num));
    		for(int i=1;i<=n;i++){
    			size[i]=1;
    		}
    		for(int i=n;i>1;i--){
    		//	cout<<f[i]<<endl;
    			size[f[i]]+=size[i];
    		} 
    		for(int i=1;i<=n;i++){
    		//	cout<<size[i]<<endl;
    			num[size[i]]++;	
    		}
    		cout<<"Case #"<<10-t<<':'<<endl;
    		for(int l=1,r;l<=n;l=r+1){
    			r=n/(n/l);//整除优化,能稍微快一点,把此处的n优化为根号n
    			int t=0;
    			for(int j=1;r*j<=n;++j) {
                    t+=num[r*j];
    			}
    			if(t*r==n) cout<<r<<endl;
    		}
    	}
    	return 0;
    }
    

    完结撒花!

  • 相关阅读:
    关于unittest框架的传参问题
    爬虫的框架:Scarpy
    Robot Frameworke在python3上搭建环境以及快捷方式的创建
    安装第三方模块报错:read time out
    操作正则表达式遇到的问题
    gil锁 线程队列 线程池
    并发编程
    网络编程传输文件
    粘包现象
    UDP协议下的socket
  • 原文地址:https://www.cnblogs.com/rpup/p/13801871.html
Copyright © 2011-2022 走看看