参考吴书P192页。
数学推导出递归公式。
用哈希判重,避免重复计算。
#include <bits/stdc++.h>
using namespace std;
const int maxn=1000+10;
const int maxp=10000+10;
struct record
{
int x,y;
long long k;
int next;
}p[maxp];
int used,f[maxn]; //存储k的单链表首指针。
int n,c[maxn]; //栈数n,个栈的容量c。
void myinsert(long long ans,int x,int y,int k)
{
p[used].x=x;
p[used].y=y;
p[used].next=f[k];
p[used].k=ans;
f[k]=used++;
}
long long myhash(int x,int y,int k)
{
int i=f[k];
while(i>=0)
{
if(p[i].x==x&&p[i].y==y) return p[i].k;
i=p[i].next;
}
return 0ll;
}
int relpos(int k,int len)
{
return k%len==0?len:k%len;
}
long long solve(int x,int y,int k)
{
long long sum=myhash(x,y,k);
if(sum)
return sum;
if(k==1)
{
sum=(long long )(x+y)*(y-x+1)/2;
myinsert(sum,x,y,k);
return sum;
}
int nx=relpos(x,c[k-1]);
int ny=relpos(y,c[k-1]);
nx=c[k-1]-nx+1;
ny=c[k-1]-ny+1;
if(y-x==nx-ny)
return solve(ny,nx,k-1);
int temp=(y-x+1)-nx-(c[k-1]-ny+1);
if(temp)
sum+=solve(1,c[k-1],k-1)*(temp/c[k-1]);
sum+=solve(ny,c[k-1],k-1)+solve(1,nx,k-1);
myinsert(sum,x,y,k);
return sum;
}
int main()
{
while(cin>>n)
{
for(int i=1;i<=n;i++)
cin>>c[i];
int x,y;
cin>>x>>y;
used=0;
memset(f,-1,sizeof(f));
cout<<solve(x,y,n)<<endl;
}
return 0;
}
不用哈希
#include <bits/stdc++.h>
using namespace std;
const int maxn=1000+10;
int n,c[maxn]; //栈数n,个栈的容量c。
int relpos(int k,int len)
{
return k%len==0?len:k%len;
}
long long solve(int x,int y,int k)
{
long long sum=0;
if(k==1)
{
sum=(long long )(x+y)*(y-x+1)/2;
return sum;
}
int nx=relpos(x,c[k-1]);
int ny=relpos(y,c[k-1]);
nx=c[k-1]-nx+1;
ny=c[k-1]-ny+1;
if(y-x==nx-ny)
return solve(ny,nx,k-1);
int temp=(y-x+1)-nx-(c[k-1]-ny+1);
if(temp)
sum+=solve(1,c[k-1],k-1)*(temp/c[k-1]);
sum+=solve(ny,c[k-1],k-1)+solve(1,nx,k-1);
return sum;
}
int main()
{
while(cin>>n)
{
for(int i=1;i<=n;i++)
cin>>c[i];
int x,y;
cin>>x>>y;
cout<<solve(x,y,n)<<endl;
}
return 0;
}