zoukankan      html  css  js  c++  java
  • BZOJ 1002 FJOI 2007 轮状病毒 暴力+找规律+高精度

    题目大意:


    思路:基尔霍夫矩阵求生成树个数,不会。

    可是能够暴力打表。(我才不会说我调试force调试了20分钟。。。

    CODE(force.cc):


    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define MAX 1000
    using namespace std;
    
    struct Edge{
    	int x,y;
    	
    	Edge(int _,int __):x(_),y(__) {}
    	Edge() {}
    }edge[MAX];
    
    int edges;
    int status;
    
    int father[MAX];
    
    int Find(int x)
    {
    	if(father[x] == x)	return x;
    	return father[x] = Find(father[x]);
    }
    
    inline bool Unite(int x,int y)
    {
    	int fx = Find(x);
    	int fy = Find(y);
    	if(fx != fy) {
    		father[fx] = fy;
    		return true;
    	}
    	return false;
    }
    
    int main()
    {
    	for(int i = 1; i <= 20; ++i) {
    		edges = 0;
    		for(int j = 1; j <= i; ++j)
    			edge[++edges] = Edge(0,j);
    		for(int j = 1; j < i; ++j)
    			edge[++edges] = Edge(j,j + 1);
    		edge[++edges] = Edge(i,1);
    		int ans = 0;
    		for(int j = 1; j <= (1 << edges); ++j) {
    			int added = 0;
    			for(int k = 0; k <= i; ++k)
    				father[k] = k;
    			for(int k = 0; k < edges; ++k)
    				added += (j >> k)&1;
    			if(added  != i)	continue;
    			added = 0;
    			for(int k = 0; k < edges; ++k)
    				if((j >> k)&1)
    					added += Unite(edge[k + 1].x,edge[k + 1].y);
    			ans += (added == i);
    		}
    		cout << i << ':' << ans << endl;
    	}
    	return 0;
    }


    打出的表是这种。。


    后面的数太大了爆了。


    非常明显能够看出奇数的数都是全然平方数。

    把它们开跟,然后经过艰苦卓绝的分析之后,得到了一个递推式:

    f[i] = f[i - 1] + Σf[j] + 2 (j∈[1,i - 1]),答案是f[n] ^ 2

    有了这个结论,偶数的就好办了。能够看到,偶数的除以5之后也是全然平方数,和上面非常像,它的递推式是:

    f[i] = f[i - 1] + Σf[j] + 1 (j∈[i,i - 1]),答案是f[n] ^ 2 * 5

    至于为什么递推式长这样,谜。


    CODE:


    #include <cstdio>
    #include <iomanip>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define BASE 10000
    #define MAX 1010
    using namespace std;
    
    struct BigInt{
    	int num[MAX],len;
    	
    	BigInt(int _ = 0) {
    		memset(num,0,sizeof(num));
    		len = _ ? 1:0;
    		num[1] = _;
    	}
    	BigInt operator +(const BigInt &a)const {
    		BigInt re;
    		re.len = max(len,a.len);
    		int temp = 0;
    		for(int i = 1; i <= re.len; ++i) {
    			re.num[i] = num[i] + a.num[i] + temp;
    			temp = re.num[i] / BASE;
    			re.num[i] %= BASE;
    		}
    		if(temp)	re.num[++re.len] = temp;
    		return re;
    	}
    	BigInt operator *(const BigInt &a)const {
    		BigInt re;
    		for(int i = 1; i <= len; ++i)
    			for(int j = 1; j <= a.len; ++j) {
    				re.num[i + j - 1] += num[i] * a.num[j];
    				re.num[i + j] += re.num[i + j - 1] / BASE;
    				re.num[i + j - 1] %= BASE;
    			}
    		re.len = len + a.len;
    		if(!re.num[re.len])	--re.len;
    		return re;
    	}
    };
    
    ostream &operator <<(ostream &os,const BigInt &a)
    {
    	os << a.num[a.len];
    	for(int i = a.len - 1; i; --i)
    		os << fixed << setw(4) << setfill('0') << a.num[i];
    	return os;
    }
    
    int k;
    BigInt f[110],g[110];
    
    int main()
    {
    	cin >> k;
    	if(k&1) {
    		k = (k + 1) >> 1;
    		f[1] = BigInt(1),f[2] = BigInt(4);
    		g[1] = BigInt(1),g[2] = BigInt(5);
    		for(int i = 3; i <= k; ++i) {
    			f[i] = f[i - 1] + g[i - 1] + BigInt(2);
    			g[i] = g[i - 1] + f[i];
    		}
    		cout << f[k] * f[k] << endl;
    	}
    	else {
    		k >>= 1;
    		f[1] = BigInt(1),f[2] = BigInt(3);
    		g[1] = BigInt(1),g[2] = BigInt(4);
    		for(int i = 3; i <= k; ++i) {
    			f[i] = f[i - 1] + g[i - 1] + BigInt(1);
    			g[i] = g[i - 1] + f[i];
    		}
    		cout << f[k] * f[k] * BigInt(5) << endl;
    	}
    	return 0;
    }


  • 相关阅读:
    ubuntu18.04安装g2o
    akka学习
    spark学习记录-2
    spark学习记录-1
    c++ string需要注意的地方
    clion server激活地址
    【转】c++面试基础
    c++反射概念-简单介绍
    死锁的理解
    c++ 反射类型
  • 原文地址:https://www.cnblogs.com/cxchanpin/p/6993363.html
Copyright © 2011-2022 走看看