動態規劃 BZOJ 1002 輪狀病毒

2021-06-21 07:38:18 字數 4010 閱讀 1532

time limit: 1 sec  

memory limit: 162 mb

submit: 1947  

solved: 1056 [

submit][

status]

第一行有1個正整數n。

將程式設計計算出的不同的n輪狀病毒數輸出 3

16題意:給出乙個n各節點的「輪子」圖,中間的節點不算入n中,你要選取一些邊,使得邊和點能構成一顆樹,問有多少種取法。

思路:我們把中間那個節點作為樹的根,然後其他節點放在第一層排成一條直線,那麼我們要做的就是把他們分成若干組,同乙個組內連成一條直線,根與其中的乙個點相連,那麼我們用g[n]表示把n個節點任意分組後有多少種取法,注意根和乙個組的點相連時可能會有多個,那麼g[n]=sum,但是考慮到這是乙個環,我們對每個節點進行標號,分別為1,2,3,4......n,那麼g[x]算出的其實是以1為頭結點能有節點數為x能有多少種取法,那麼我們換乙個頭結點,變成n,1,2,3,4.....n-1,此時我們的包含頭結點那一段的最少長度應該為2,必須要覆蓋到1,不然就算重複了。以此類推,轉移方程就是f[i]=g[i]+sum

**:

#include#include#include#include#include#include#include#includeusing namespace std;

const int maxn = 100 + 5;

#define maxn 9999

#define maxsize 10

#define dlen 4

class bignum

//建構函式

bignum(const int); //將乙個int型別的變數轉化為大數

bignum(const char*); //將乙個字串型別的變數轉化為大數

bignum(const bignum &); //拷貝建構函式

bignum &operator=(const bignum &); //過載賦值運算子,大數之間進行賦值運算

friend istream& operator>>(istream&, bignum&); //過載輸入運算子

friend ostream& operator<

bignum operator+(const bignum &) const; //過載加法運算子,兩個大數之間的相加運算

bignum operator-(const bignum &) const; //過載減法運算子,兩個大數之間的相減運算

bignum operator*(const bignum &) const; //過載乘法運算子,兩個大數之間的相乘運算

bignum operator/(const int &) const; //過載除法運算子,大數對乙個整數進行相除運算

bignum operator^(const int &) const; //大數的n次方運算

int operator%(const int &) const; //大數對乙個int型別的變數進行取模運算

bool operator>(const bignum & t)const; //大數和另乙個大數的大小比較

bool operator>(const int & t)const; //大數和乙個int型別的變數的大小比較

void print(); //輸出大數

};bignum f[maxn];

bignum g[maxn];

int n;

void pre_init()

for (int j = i; j > 1; --j)

for (int len = i + 2 - j; len <= i; ++len)

f[i] = f[i] + g[i - len] * len; }}

int main()

}bignum::bignum(const int b) //將乙個int型別的變數轉化為大數

a[len++] = d;

}bignum::bignum(const char*s) //將乙個字串型別的變數轉化為大數

}bignum::bignum(const bignum & t) : len(t.len) //拷貝建構函式

bignum & bignum::operator=(const bignum & n) //過載賦值運算子,大數之間進行賦值運算

istream& operator>>(istream & in, bignum & b) //過載輸入運算子

b.a[count] = sum;

count++;

} b.len = count++;

return in;

}ostream& operator<

return out;

}bignum bignum::operator+(const bignum & t) const //兩個大數之間的相加運算

} if (t.a[big] != 0)

t.len = big + 1;

else

t.len = big;

return t;

}bignum bignum::operator-(const bignum & t) const //兩個大數之間的相減運算

else

big = t1.len;

for (i = 0; i < big; i++)

else

t1.a[i] -= t2.a[i];

} t1.len = big;

while (t1.a[len - 1] == 0 && t1.len > 1)

if (flag)

t1.a[big - 1] = 0 - t1.a[big - 1];

return t1;

}bignum bignum::operator*(const bignum & t) const //兩個大數之間的相乘運算

else

}if (up != 0)

ret.a[i + j] = up;

} ret.len = i + j;

while (ret.a[ret.len - 1] == 0 && ret.len > 1)

ret.len--;

return ret;

}bignum bignum::operator/(const int & b) const //大數對乙個整數進行相除運算

ret.len = len;

while (ret.a[ret.len - 1] == 0 && ret.len > 1)

ret.len--;

return ret;

}int bignum::operator %(const int & b) const //大數對乙個int型別的變數進行取模運算

return d;

}bignum bignum::operator^(const int & n) const //大數的n次方運算

m -= i;

ret = ret*t;

if (m == 1)

ret = ret*(*this);

} return ret;

}bool bignum::operator>(const bignum & t) const //大數和另乙個大數的大小比較

else

return false;

}bool bignum::operator >(const int & t) const //大數和乙個int型別的變數的大小比較

void bignum::print() //輸出大數

cout << endl;

}

BZOJ 1002 輪狀病毒

time limit 1 sec memory limit 162 mb submit status 給定n n 100 程式設計計算有多少個不同的n輪狀病毒。第一行有1個正整數n。將程式設計計算出的不同的n輪狀病毒數輸出 3 16 第一眼看上去,n 100 不錯 打表 於是就寫了乙個暴力搜尋 可是...

bzoj 1002 輪狀病毒 打表

一眼看到資料範圍,輸入只有1個n,n 100果斷打表。然而好像跑錶的複雜度不茲磁啊,要跑幾年。所以要打表找規律。include 這是小資料打表 include using namespace std struct eb 100005 int cnt,n int use 100005 int fa 1...

bzoj1002 輪狀病毒 遞推 高精度

輪狀病毒有很多變種,所有輪狀病毒的變種都是從乙個輪狀基產生的。乙個n輪狀基由圓環上n個不同的基原子 和圓心處乙個核原子構成的,2個原子之間的邊表示這2個原子之間的資訊通道。如下圖所示 n輪狀病毒的產生規律是在乙個n輪狀基中刪去若干條邊,使得各原子之間有唯一的資訊通道,例如共有16個不 同的3輪狀病毒...