题目大意:
给定一个1-n的序列,每一次操作把序列无限延长之后取前面的bi位,求最后每个数字出现的次数。
思路:
首先观察到要是bi>bi+1,那么bi就是没有意义的,这样以后整个操作序列就变成了单调递增的。
考虑从反面推出每一段序列在最后的序列中的出现的次数。具体地,对于每一段序列,我们要把它划分为若干个之前的序列。
对于倒数第一次操作之后的序列它在最后的序列中出现了一次,倒数第二次操作之后的序列可以看它在最后一段序列中出现了几次,然后他的出现次数就是它在后一段序列中的出现次数*后一段序列的出现次数。显然这样还会有剩余,剩余的部分继续分成前面的序列就好了。
#include<bits/stdc++.h>
#define REP(i,a,b) for(int i=a;i<=b;++i)
#define DREP(i,a,b) for(int i=a;i>=b;--i)
typedef long long ll;
using namespace std;
void File(){
freopen("l.in","r",stdin);
freopen("l.out","w",stdout);
}
const int maxn=1e5+10;
int n,m,tp;
ll b[maxn],f[maxn],ans[maxn];
int main(){
File();
scanf("%d%d",&n,&m);
b[++tp]=n;
REP(i,1,m){
scanf("%lld",&b[++tp]);
while(tp>1 && b[tp]<b[tp-1])b[tp-1]=b[tp--];
}
f[tp]=1;
DREP(i,tp-1,0){
ll len=b[i+1];
while(len>b[1]){
int pos=upper_bound(b+1,b+i+1,len)-b-1;
f[pos]+=len/b[pos]*f[i+1];
len%=b[pos];
}
ans[len]+=f[i+1];
}
DREP(i,b[1],1)ans[i]+=ans[i+1];
REP(i,1,n)printf("%lld\n",ans[i]);
return 0;
}