洛谷 P1062 数列[解法一:搜索]

题目描述

给定一个正整数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);
    }
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值