题目描述

给定一个正整数k(3≤k≤15),把所有k的方幂及所有有限个互不相等的k的方幂之和构成一个递增的序列,例如,当k=3时,这个序列是:

1,3,4,9,10,12,13,…

(该序列实际上就是:3^0,3^1,3^0+3^1,3^2,3^0+3^2,3^1+3^2,3^0+3^1+3^2,…)

请你求出这个序列的第N项的值(用10进制数表示)。

例如,对于k=3,N=100,正确答案应该是981。
输入输出格式
输入格式:

输入文件只有1行,为2个正整数,用一个空格隔开:

k N (k、N的含义与上述的问题描述一致,且3≤k≤15,10≤N≤1000)。

输出格式:

输出文件为计算结果,是一个正整数(在所有的测试数据中,结果均不超过2.1*109)。(整数前不要有空格和其他符号)。

输入输出样例
输入样例#1:

3 100

输出样例#1:

981

说明

NOIP 2006 普及组 第四题


【分析】

论没看题解就做题的下场
二进制啥的不说了…下面全都是…
这其实是一道搜索好题…
思路:先将拆分后最大次幂为i的个数用组合数搞出来,放进数组dp中,以缩小搜索范围。
然后跑前缀和,找出满足条件时最大次幂是多少(单调增),然后跑一波dfs,把得到的结果排序。
只放思路了…代码略长但易懂,仅供参考


【代码】

//数列 
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define M(a) memset(a,0,sizeof a)
#define fo(i,j,k) for(i=j;i<=k;i++)
using namespace std;
ll dp[1005],c[1005][1005],cun[1005],fina[1005];;
ll n,k,ans,cnt,w,num,flag,tot;
inline void jilu() //记录
{
ll i,j;
ans=flag;
fo(i,1,w)
ans+=pow(k,cun[i]);
fina[++tot]=ans;
}
inline void dfs(ll dep)
{
ll i,j;
if(dep>w)
{
jilu();
return;
}
fo(i,cun[dep-1]+1,num-(w-dep))
cun[dep]=i,dfs(dep+1);
}
inline void get() //组合数递推
{
ll i,j;
fo(i,0,n) c[i][0]=1;
fo(i,1,n)
fo(j,1,i)
c[i][j]=c[i-1][j]+c[i-1][j-1];
}
inline void find(ll x)
{
ll i,j,sum=0;
cun[0]=-1;
fo(i,0,x-1) n-=dp[i]; //将前面的个数都减去
num=x-1;
flag=pow(k,x);
fo(w,0,x) //枚举在x之前取几个数,w为取的数的个数
dfs(1);
sort(fina+1,fina+tot+1); //由于结果不单调,所以排序
printf("%lld\n",fina[n]);
exit(0);
}
int main()
{
ll i,j,sum=1;
scanf("%lld%lld",&k,&n);
if(n==1) {printf("1\n");return 0;}
get();
dp[0]=1;
fo(i,1,n)
{
fo(j,0,i)
dp[i]+=c[i][j];
sum+=dp[i]; //前缀和
if(sum>=n) //找出范围
find(i);
}
}