HDU 5587 Array(递归)

来源:互联网 发布:新点招投标软件下载 编辑:程序博客网 时间:2024/06/06 08:59

题目链接
题意:他将他当天的数列复制一遍,放在数列尾,并在两个数列间用0隔开。Vicky想做些改变,于是他将当天新产生的所有数字(包括0)全加1。Vicky现在想考考你,经过100天后,这个数列的前M项和是多少?。
解法:先预处理,第i天的长度和和。然后递归,m<2^64;

//#define CF#ifndef CF#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>#include<iostream>#include<string>#include<set>#include<vector>#else#include<bits/stdc++.h>#endif // CFusing namespace std;#define LL long long#define pb push_back#define X first#define Y second#define cl(a,b) memset(a,b,sizeof(a))typedef pair<long long ,long long > P;const int maxn=100005;const LL inf=1LL<<50;const LL mod=1e9+7;LL sum[64];LL len[64];void init(){    sum[1]=len[1]=1;    for(int i=2;i<64;i++){        sum[i]=sum[i-1]*2LL+len[i-1]+1;        len[i]=len[i-1]*2LL+1;    }}LL slove(LL m){    int i;    for(i=1;len[i]<=m;i++);i--;    if(len[i]==m)return sum[i];    if(len[i]==m-1)return sum[i]+1;    return sum[i]+slove(m-(len[i]+1))+m-len[i];}int main() {    int T;scanf("%d",&T);    init();    while(T--){        LL n;scanf("%lld",&n);        printf("%lld\n",slove(n));    }    return 0;}
0 0
原创粉丝点击