• BZOJ1002輪狀病毒 暴搜 + 找規律 + 高精度


    @[暴搜, 找規律, 高精度]

    Description

    轮状病毒有很多变种,所有轮状病毒的变种都是从一个轮状基产生的。一个(n)轮状基由圆环上(n)个不同的基原子和圆心处一个核原子构成的,2个原子之间的边表示这2个原子之间的信息通道。如下图所示
    enter image description here
    (n)轮状病毒的产生规律是在一个(n)轮状基中删去若干条边,使得各原子之间有唯一的信息通道,例如共有(16)个不
    同的3轮状病毒,如下图所示
    enter image description here
    现给定(n)((n <= 100)),编程计算有多少个不同的n轮状病毒

    Input

    1个正整数n

    Output

    计算出的不同的n轮状病毒数输出

    Sample Input

    3
    

    Sample Output

    16
    

    Solution

    先暴搜找規律(結果爆搜就打了好久(QAQ))

    #include<cstdio>
    #include<cctype>
    #include<cstring>
    using namespace std;
    inline int read()
    {
        int x = 0, flag = 1;;
        char c;
        while(! isdigit(c = getchar()))
            if(c == '-')
                flag *= - 1;
        while(isdigit(c))
            x = x * 10 + c - '0', c = getchar();
        return x * flag;
    }
    void println(int x)
    {
        if(x < 0)
            putchar('-'), x *= - 1;
        if(x == 0)
            putchar('0');
        int ans[10], top = 0;
        while(x)
            ans[top ++] = x % 10, x /= 10;
        for(; top; top --)
            putchar(ans[top - 1] + '0');
        putchar('
    ');
    }
    int n;
    struct Edge
    {
    	int u, v;
    }G[100];
    int ans;
    int fa[16];
    int find(int x)
    {
    	if(fa[x] == x)
    		return x;
    	return fa[x] = find(fa[x]);
    }
    void search(int x, int top, int cnt)
    {
    	if(cnt == n)
    	{
    		ans ++;
    		return;
    	}
    	if(x == top)
    		return;
     	search(x + 1, top, cnt);
    	int _fa[16]; //并查集很執行難撤回操作, 因此只能用這種比較笨的辦法來搞
    	for(int i = 0; i <= n; i ++)
    		_fa[i] = fa[i];
    	int fu = find(G[x].u), fv = find(G[x].v);
    	if(fu == fv)
    		return;
    	fa[fu] = fv;
    	search(x + 1, top, cnt + 1);
    	for(int i = 0; i <= n; i ++)
    		fa[i] = _fa[i];
    }
    int main()
    {
    	for(int i = 2; i < 16; i ++)
    	{
    		n = i;
    		for(int j = 0; j < n; j ++)
    			G[j].u = 0, G[j].v = j + 1;
    		for(int j = n; j < (n << 1); j ++)
    			G[j].u = j - n + 1, G[j].v = j - n + 2;
    		G[(n << 1) - 1].v = 1;
    		for(int i = 0; i <= n; i ++)
    			fa[i] = i;
    		ans = 0;
    		search(0, n << 1, 0);
    		println(ans);
    	}
    }
    

    得到輸出數據

    5
    16
    45
    121
    320
    841
    2205
    5776
    15125
    39601
    103680
    271441
    710645
    1860496
    
    --------------------------------
    Process exited after 70.46 seconds with return value 0
    请按任意键继续. . .
    

    通過待定係數法可得, 對於(n)輪狀病毒有種類數
    (f(n) = f(n - 1) * 3 - f(n - 2) + 2)
    注意到當 (n = 100)(f(n)) 會變得很大, 所以要寫高精度...

    #include<cstdio>
    #include<cctype>
    #include<cstring>
    using namespace std;
    inline int read()
    {
        int x = 0, flag = 1;;
        char c;
        while(! isgraph(c = getchar()))
            if(c == '-')
                flag *= - 1;
        while(isgraph(c))
            x = x * 10 + c - '0', c = getchar();
        return x * flag;
    }
    void println(int x)
    {
        if(x < 0)
            putchar('-'), x *= - 1;
        if(x == 0)
            putchar('0');
        int ans[10], top = 0;
        while(x)
            ans[top ++] = x % 10, x /= 10;
        for(; top; top --)
            putchar(ans[top - 1] + '0');
        putchar('
    ');
    }
    const int N = 1 << 7;
    struct Giant
    {
    	int dig[1 << 10];
    	int top;
    }f[N];
    Giant operator *(Giant x, int y)
    {
    	for(int i = 0; i < x.top; i ++)
    		x.dig[i] *= y;
    	for(int i = 0; i < x.top; i ++)
    		x.dig[i + 1] += x.dig[i] / 10, x.dig[i] %= 10;
    	if(x.dig[x.top])
    		x.top ++;
    	return x;
    }
    Giant operator -(Giant x, Giant y)
    {
    	for(int i = 0; i < x.top; i ++)
    	{
    		x.dig[i] -= y.dig[i];
    		if(x.dig[i] < 0)
    			x.dig[i] += 10, x.dig[i + 1] --;
    	}
    	if(! x.dig[x.top - 1])
    		x.top --;
    	return x;
    }
    Giant operator +(Giant x, int y)
    {
    	x.dig[0] += y;
    	for(int i = 0; i < x.top; i ++)
    		x.dig[i + 1] += x.dig[i] / 10, x.dig[i] = x.dig[i] % 10;
    	if(x.dig[x.top])
    		x.top ++;
    	return x;
    }
    void println(Giant &x)
    {
    	for(int i = x.top; i; i --)
    		putchar(x.dig[i - 1] + '0');
    	putchar('
    ');
    }
    int main()
    {
    	int n = read();
    	memset(f, 0, sizeof(f));
    	f[2].dig[0] = 5, f[2].top = 1;
    	f[3].dig[0] = 6, f[3].dig[1] = 1, f[3].top = 2;
    	for(int i = 4; i <= n; i ++)
    		f[i] = f[i - 1] * 3 - f[i - 2] + 2;
    	println(f[n]);
    }
    
  • 相关阅读:
    完整java开发中JDBC连接数据库代码和步骤
    2007最后一贴
    ajax数据加载经验分享
    vs2008中文版提供下载(包含中文msdn)
    修改服务器控件的ID和Name
    你使用控件吗?会用吗?
    自定义控件集
    asp.net控件开发基础示例代码打包
    javascript好文章收藏
    wpf学习笔记简单绑定
  • 原文地址:https://www.cnblogs.com/ZeonfaiHo/p/6483022.html
Copyright © 2020-2023  润新知