這裡放傳送門
這題比較關鍵的一點就是注意到題目裡說兩把劍本質不同當且僅當存在一種數字的出現次數不同。也就是說這個東西跟數字的出現順序是無關的。那麼我們可以考慮確定一種排序方式讓每一種本質不同的解都唯一對應一種看起來比較好做的序列。
因為每兩個元素相差必須是1,通過多畫幾個試試觀察可以發現每一種合法解都可以排列成一種這樣的序列:設序列中最大元素是k,首先把1..k按照順序排成一串,然後在中間的k-1個空擋裡插入形如(i+1,i)這樣的數對。例如1 2 3 2 1 2 3 2 1這組解就可以排列成12 1 2 123 23這個樣子。
注意到這一點就有思路了。如果固定了長度n和最大出現的數字k,那麼實際上就是要在k-1個空位置中插入(n-k)/2個數對。插入的數具體是什麼是由它的位置決定的。那麼這就是乙個經典的插板法可以解決的問題了。
有乙個問題是如果n-k是奇數怎麼辦,實際上多出來的那個數字是可以把它固定被放在最後乙個位置上的。比如說是1 2 3 2 1 2 3 2 1 2,按照上面的方法「排序」以後可以變成12 1 2 123 232。可以發現這種變換方式對於每一種本質不同的數列是唯一的。所以直接下取整就可以了。
這樣的話我們就有了一種o(
nk) 的求解方式,就是先列舉數列長度再列舉出現的最大數字。也就是下面**裡面注釋掉的那部分。
接下來考慮優化這個做法。乙個比較好想到的思路就是因為在做組合數的時候是連續列舉的,可以考慮利用公式c(
n,m)
=c(n
−1,m
)+c(
n−1,
m−1)
來進行合併。然後通過把表打出來看一看觀察可以發現當m相同的時候n的變化是有規律的。。然後反正湊一湊然後湊出∑i
=mrc
(i,m
) 這樣能連續合併的東西大概就是這個樣子就可以o(
n)了。。
具體那個規律是啥atp找的規律看起來非常*****。。就不好意思拿出來誤導人了qaq。。
#include
#include
#include
using namespace std;
const long long mod=1e9+7;
int n,m,lim;
long long ans,mul[2000020],inv[2000020];
long long c(int n,int
m)/*long long get(int n,int
m)long long calc(int n)
printf("\n");
return sum;
}*/int main()
lim=max(n,m)+10;
mul[0]=1;inv[1]=1;inv[0]=1;
for (int i=1;i<=lim;i++) mul[i]=mul[i-1]*i
%mod;
for (int i=2;i<=lim;i++) inv[i]=(mod-mod/i)*inv[mod%i]%mod;
for (int i=1;i<=lim;i++) inv[i]=inv[i]*inv[i-1]%mod;
lim=min(m-2,n-2);
for (int i=0;i<=lim;i++)
// for (int i=0;i<=lim;i++) ans=(ans-c(i,i))%mod;
ans=(ans-(lim+1)+min(n,m))%mod;
ans=(ans+mod)%mod;
printf("%i64d\n",ans);
return
0;}
BZOJ 4402 Claris的劍 組合數學
由於存在集合等價的情況,我們就只考慮字典學最小的方案 假設最大值是ma x 那麼構造出的序列有兩種情況 1,2,1,2,1,2.3,2 3,2 3.ma x 2,max 1,ma x 2,max 1.ma x 1,2,1,2,1,2.3,2 3,2 3.ma x 2,max 1,ma x 2,max...
bzoj4402 Claris的劍(組合數學)
傳送門 思路 考慮怎麼才不會算重。顯然你的序列可以變化成 121 2.xx 1xx 1.ma x1 2 1 2.x x 1 x x 1.max 1212.xx 1xx 1.max和12 12.xx 1xx 1.ma xmax 1 1 2 1 2.x x 1 x x 1.max max 1 1212....
bzoj 4402 Claris的劍 組合數學
time limit 10 sec memory limit 256 mb submit 375 solved 213 submit status discuss claris想要鑄一把劍,這把劍必須符合他的審美,具體來說,我們可以把這把劍的不同地方的寬度看成乙個序列,這個序列要滿足以下條件 1.每...