ACM題:狼
阿新 • • 發佈:2018-12-19
第500篇文章紀念
時間飛逝啊,我竟然已經在寫第500篇文章了 回首當年艱辛的路,再看看我目前取得的的這些成績,瞬時覺得當年那些委屈和痛苦都沒有白受 當年母親一直說我搞是個錯誤的決定,但是現在她也不這麼想了,反而很支援我搞競賽 話不多說 來看這道十分具有紀念意義的題目
題目
時間限制:1000ms;空間限制:128MB
【題目描述】
當狼群作戰時,隨著群體變大,其戰鬥力就會爆炸地增長,能產生許多奇蹟。
有一個靠狼群作戰的王國,他們擁有數不清的戰狼與士兵。目前,大敵壓境,將軍要鎮守一側的n個大門,每個大門可以佈置一個士兵或一隻戰狼,當有k個連著的大門都佈置了戰狼,這k只戰狼就會形成狼群,更容易獲勝。機智的將軍已經算好,只要有一個m只狼的狼群就有把握獲勝,當然,理論上狼群的數量與大小都是多多益善,但實際要平衡好戰狼與人的關係。
那麼問題來了,這個王國的好奇寶寶想知道理論上有多少種獲勝的佈置方案,忙碌的將軍將沒時間數,就希望你寫一個程式幫幫他。
【輸入】
【輸入樣例】
5 3
【輸出樣例】
8
題目源自syy
題解
用表示這個狼群的大小不小於 滿足條件的序列必然滿足如下命題 那麼不滿足條件的序列就是對上述命題取非 統計出不滿足條件的,再用總個數減去就得到答案了 那麼現在就是要統計有多少長度為的人、狼序列,其中所有的狼群大小都嚴格小於 表示長度為的序列,最後連續個是狼 直接看方程不夠直觀,如果寫出整個二維陣列,我用橙色的線表示求和,如下圖 其中虛線的表示更新到一個不存在的狀態 可以看到,每行的第一個數都是前一行每個數的和,而後面的數是由前一行依次向右平移得來的 每行最後一個數在平移之後會被舍掉, 但是我如果不把他舍掉,而是直接接在下一行的後面,就會產生這樣的效果:
程式碼
//syy的題
#include <bits/stdc++.h>
#define ll long long
#define maxn 10000010
#define mod 10000007ll
using namespace std;
ll f[maxn], s[maxn];
ll read(ll x=0)
{
ll c, f=1;
for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-1;
for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+c-48;
return f*x;
}
ll fastpow(ll a, ll b)
{
ll t=a, ans=1;
for(;b;b>>=1,t=t*t%mod)if(b&1)ans=ans*t%mod;
return ans;
}
void preprocess(ll n, ll m)
{
ll i;
f[0]=s[0]=1;
for(i=1;i<=n+1;i++)
{
f[i]=s[i-1];
if(i>=m-1)f[i]-=s[i-m-1];
f[i]%=mod;
s[i]=(s[i-1]+f[i])%mod;
}
}
int main()
{
ll N=read(), M=read(), ans=0, i;
preprocess(N,M);
ans=fastpow(2,N)-f[N+1];
cout<<(ans%mod+mod)%mod;
return 0;
}
測試資料
輸入1:
5 3
輸出1:
8
輸入2:
10 3
輸出2:
520
輸入3:
1000 10
輸出3:
8930315
輸入4:
1811 1
輸出4:
2657145
輸入5:
1991 9
輸出5:
3969738
輸入6:
190 2
輸出6:
6873368
輸入7:
83 6
輸出7:
4775625
輸入8:
8 5
輸出8:
20
輸入9:
29 4
輸出9:
5808696
輸入10:
883 2
輸出10:
2206875
輸入11:
10000000 5000000
輸出11:
8791226
輸入12:
9876543 1234567
輸出12:
7690719
輸入13:
9999979 7688907
輸出13:
4659058