problem death sequence
題目大意
排成一行的約瑟夫問題。
n個人排成一行,從第一個人開始,每個k個人報數,報到數的人被殺死,剩下的人重新排成一行再報數。
一共q個詢問,每次詢問第qi個死的人是誰。
n <= 3000000 , q <= 1000000 , k>=1 。
解題分析
顯然每一輪遊戲可以看做是一個子問題。
假設編號為0~n-1,若某輪中某人的編號為i,如果i被k整除則被殺,否則在下輪中編號為i-i/k-1。
dp[i]表示編號為i的人可以存活幾輪,那麼dp[i]=i % k ? dp[i-i/k-1] : 0 。
再用一個陣列s[i]記錄一下前i輪一共死了多少人。
這樣就可以在o(n)時間內預處理出一個答案序列。
參考程式
1 #include2 #include3 #include4 #include5 #include6 #include7 #includeview code8 #include9 #include10 #include
11 #include12 #include13
14using
namespace
std;
15 typedef long
long
ll;16 typedef unsigned long
long
ull;
1718
#define rep(i,k,n) for(int i=(k);i<=(n);i++)
19#define rep0(i,n) for(int i=0;i
20#define red(i,k,n) for(int i=(k);i>=(n);i--)
21#define sqr(x) ((x)*(x))
22#define clr(x,y) memset((x),(y),sizeof(x))
23#define pb push_back
24#define mod 1000000007
2526
const
int maxn=3000300;27
intn,k,q,tot;
28int
f[maxn],s[maxn],ans[maxn],a[maxn];
2930
void
init()
3141 f[0]=0
;42 rep(i,0,n-1
)46 rep(i,0,n-1)50
//rep(i,1,n) printf("%d %d\n",i,ans[i]+1 );51}
5253
intmain()
5466}67
68return0;
69 }