2480: 神奇的序列
时间限制: 4 Sec 内存限制: 256 MB提交: 34 解决: 16
[ 提交][ 状态][ 讨论版]
题目描述
序列a如下:
a[0] = A;
a[1] = B;
a[i] = a[pp] * a[qq]; ( i>=2,pp = 向下取整(i/k1),qq = 向下取整(i/k2) )
有Q次询问,每次询问输入pos,请输出a[pos]%mod。
输入
第一行输入五个整数A,B,k1,k2,mod。
第二行输入一个整数Q。
接下来Q行每行输入一个整数pos。
1<=A<=100
1<=B<=100
2<=k1,k2<=1e14
1<=mod<=1e9+7
1<=Q<=100000
1<=pos<=1e14
输出
输出Q行,每行表示a[pos]%mod。
样例输入
45 87 2 5 1000000007
11
0
1
2
3
4
5
6
7
8
9
10
样例输出
45
87
3915
3915
176175
340605
340605
340605
15327225
15327225
333468568
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<queue> #include<stack> #include<vector> #include<map> #include<algorithm> using namespace std; #define ll long long #define ms(a,b) memset(a,b,siezof(a)) const int M=1e5+10; const int inf=0x3f3f3f3f; int i,j,k,n,m; map<ll,ll>p; ll a,b,k1,k2,mod; ll rec(ll x) { if(x==0)return a; if(x==1)return b; if(p.count(x))return p[x]; p[x]=((rec(x/k1)%mod)*(rec(x/k2)%mod))%mod; return p[x]; } int main() { while(~scanf("%lld%lld%lld%lld%lld",&a,&b,&k1,&k2,&mod)){ int q; p.clear(); scanf("%d",&q); while(q--){ ll pos; scanf("%lld",&pos); printf("%lld\n",rec(pos)%mod); } } return 0; }
虽然理解了,但是却不理解为什么可以直接储存,然后自己写了个小递归:
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<queue> #include<stack> #include<vector> #include<map> #include<algorithm> using namespace std; #define ll long long #define ms(a,b) memset(a,b,siezof(a)) const int M=1e5+10; const int inf=0x3f3f3f3f; int i,j,k,n,m; int rec(int x) { cout<<" "<<x<<endl; if(x==1)return 1; if(x==2)return 2; return rec(x/2+1)*rec(x/2); } int main() { scanf("%d",&n); cout<<" "<<rec(n)<<endl; return 0; }
可以看出递归的过程,因此可以储存已经算过的答案