当前位置: 代码迷 >> 综合 >> bzoj 1002 轮状病毒(高精度 + 找规律乱搞)
  详细解决方案

bzoj 1002 轮状病毒(高精度 + 找规律乱搞)

热度:108   发布时间:2023-11-21 12:03:49.0

1002: [FJOI2007]轮状病毒

Time Limit: 1 Sec   Memory Limit: 162 MB
Submit: 5946   Solved: 3243
[Submit][Status][Discuss]

Description

  轮状病毒有很多变种,所有轮状病毒的变种都是从一个轮状基产生的。一个N轮状基由圆环上N个不同的基原子
和圆心处一个核原子构成的,2个原子之间的边表示这2个原子之间的信息通道。如下图所示

  N轮状病毒的产生规律是在一个N轮状基中删去若干条边,使得各原子之间有唯一的信息通道,例如共有16个不
同的3轮状病毒,如下图所示

现给定n(N<=100),编程计算有多少个不同的n轮状病毒

Input

  第一行有1个正整数n

Output

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

Sample Input

3

Sample Output

16

HINT

Source


听说这题是基尔霍夫矩阵……我其实是乱搞

在数学课上不想听,就开始想这道题,然后画了二十分钟的图……找到了前几项如下:

1  5  16  45  121 ……

然后看到了什么呢?平方!

但是5, 45怎么解释呢?我又画了n=6的图, 320,然后作出猜想,偶数项可能是某个数的平方-4,2是3^2 - 4,4是7^2 - 4……

那么底数又有什么规律呢?1, 3, 4, 7, 11, 18……

4 = 3 + 1

7 = 4 + 3

11 = 7 + 4

就是个fibonacci,只是前两项不同而已

再套上高精度,借用黄学长的板子

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define rad 1000
ll n;
struct data
{int v[10005],l;data(){memset(v,0,sizeof(v));l=0;}
};
void print(data a)
{for(int i=a.l;i;i--)printf("%d",a.v[i]);printf("\n");
}
bool operator>(data a,data b)
{if(a.l>b.l)return 1;if(a.l<b.l)return 0;for(int i=a.l;i;i--)if(a.v[i]>b.v[i])return 1;else if(a.v[i]<b.v[i])return 0;return 0;
}
data operator*(data a,data b)
{data c;for(int i=1;i<=a.l;i++)for(int j=1;j<=b.l;j++)c.v[i+j-1]+=a.v[i]*b.v[j];for(int i=1;i<=a.l+b.l;i++){if(c.v[i]>=10){c.v[i+1]+=c.v[i]/10;c.v[i]%=10;}if(c.v[i])c.l=i;}return c;
}
data operator-(data a,data b)
{data c;for(int i=1;i<=a.l;i++){c.v[i]=a.v[i]-b.v[i];if(c.v[i]<0){c.v[i]+=10;a.v[i+1]--;}}c.l=a.l;while(!c.v[c.l]&&c.l)c.l--;return c;
}
data operator+(data a,data b)
{data c;c.l=max(a.l,b.l);for(int i=1;i<=c.l;i++)c.v[i]=a.v[i]+b.v[i];for(int i=1;i<=c.l;i++)if(c.v[i]>=10){c.v[i]%=10;c.v[i+1]++;}while(c.v[c.l+1])c.l++;return c;
}
data F[1001];
data ans;
signed main() {scanf("%lld", &n);F[1].v[1] = 1;F[2].v[1] = 3;F[1].l = 1;F[2].l = 1;data dec;dec.v[1] = 4; dec.l = 1;for(int i = 3; i <= n; i++) F[i] = F[i - 1] + F[i - 2];if(n & 1) ans = F[n] * F[n];else ans = F[n] * F[n] - dec;print(ans);puts("");return 0;
}