Make Triangle
[介紹]
用(n-3)條對角線去切割凸n邊形,使之變爲三角形,詢問方案總數。~呵呵
[sol]
此題關鍵部分是枚舉圖形的哪一維才能確保不重複計數,其實題意上有強調,選取的對角線不能相交(在圖
形內部),想象一下圖形最後的狀態,每一條邊都在一個三角形內,每個邊都對應一個點,而這條邊對應不
同頂點的時候,走會出現對角線相交的情況,即從A、B兩點外的兩個點分別向A、B引直線,這些直線肯定
會相交,所以通過枚舉一條邊對應的不同頂點的方式避免重複的情況。。
枚舉1~n這條邊對應的不同頂點j(2<=j<=n - 1)
f[n] = ∑f[j] * f[n - i + 1]
[吐槽]
本來想通過枚舉新類型對角線的方式來搞(這樣不會重複),但是一條對角線把圖形分成兩部分的同時,子
圖形的對角線(對子圖形包含一點的對角線但是對於整體這個圖形卻包含了多點)混淆了類型……
另外f數組定義爲int類型的話。。1LL * f [i]*f[n - i + 1] (前面加一個1LL)
#include<cstdio>
#include<iostream>
using namespace std;
const int N = 1000 + 5;
const long long P = 100007;
int f[N];
int main()
{
f[2] = 1;
f[3] = 1;
for(int i = 4; i <= 1000; i++)
{
long long tmp = 0;
for(int j = 2; j < i; j++)
tmp = (tmp + 1LL * f[j] * f[i - j + 1]) % P;
f[i] = tmp;
}
int T;
scanf("%d", &T);
while(T--)
{
int k;
scanf("%d", &k);
printf("%d\n", f[k]);
}
return 0;
}
Regular Bridge
[sol]
首先要知道,對於無向圖來說,所有節點的度數之和一定爲偶數,或者說奇度點的個數爲偶數。這樣當k爲
偶數時,假設存在圖A滿足要求,把圖A的橋拆開,那麼分開的兩個子圖都只有一個奇度點,顯然與上面的
結論矛盾,因此k爲偶數時無解。
當k爲奇數時,我們先構造出橋的一點,編號爲1,連接2,3,4,…k點,另外的一個度在橋的另一邊,我們
另外再構造兩個點(k+1,k+2),這兩個點連接其餘的所有的點,2、3、4、、k再連接k-1個點就可以
#include<cstdio>
#include<iostream>
using namespace std;
const int N = 11000;
int num = 0, x[N], y[N];
void add(int s, int t)
{
num++;
x[num] = s;
y[num] = t;
}
int main()
{
int n;
scanf("%d", &n);
if (n % 2 ==0)
{
printf("NO");
return 0;
}
if(n == 1)
{
printf("YES\n2 1\n1 2");
return 0;
}
for(int i = 2; i <= n; i++)
add(1, i);
for(int i = 2; i <=n; i++)
if (i % 2 == 0)
{
for(int j = i + 2; j <= n; j++)
add(i, j);
} else
{
for(int j = i + 1; j <= n; j++)
add(i, j);
}
for(int i = 2; i <= n; i++)
{
add(n + 1, i);
add(n + 2, i);
}
add(n + 1, n + 2);
printf("YES\n");
printf("%d %d\n", 2 * n + 4, 2 * num + 1);
for(int i = 1; i <= num; i++)
{
printf("%d %d\n", x[i], y[i]);
printf("%d %d\n", x[i] + n + 2, y[i] + n + 2);
}
printf("%d %d", 1, n + 3);
}