HDU 1597 二分+数学

题目链接


思路:

不知道为什么我的搜索专题出现了这道题......好像是可以折半搜索,但感觉复杂度很高,观察了一下:
第一个数:1位
第二个数:2位
......
第n个数:n位


那如果连起来,连接完第n个数,这个数的位数为:
1 + 2 + 3 + 4 ......+n


这不正是等差数列求和吗?
然后我用下面的代码简单测了一下。


#include <bits/stdc++.h>
using namespace std;

int main(){
	long long ans = 1;
	int i;
	for(i=1 ;i<=31 ;i++){
		ans *= 2;
	}
	cout << ans << endl;
	long long k = 1;
	while(k*(k+1)/2 <= ans){
		k++;
	}
	printf("k = %d\n",k);
	return 0;
}


发现哪怕是2^31多位,也不过是65000左右的等差数列求和,那么下面就很简单了。


我先开一个65000左右大小的数组,预处理a[i] = i*(i+1)/2。对于每一个给定的位数k放进a数组里面二分搜索,找到下限pos,用k-(pos)*(pos+1)/2,剩下的就是从1开始的属于最后一个数的一个数串,然后对9取余即可,若取余为0,则说明刚好剩下9个数(或9的倍数),那么输出9,否则直接输出即可。


1A代码:

#include <bits/stdc++.h>
using namespace std;

const int maxn = 65550;
long long a[maxn];

void init(void){
	long long i;
	a[0] = 0;
	for(i=1 ;i<maxn ;i++){
		a[i] = i*(i+1)/2;
	}
}

int main(){
	init();
	int k;
	scanf("%d",&k);
	while(k--){
		long long n,pos;
		scanf("%lld",&n);
		pos = lower_bound(a,a+maxn,n) - a;
		while(pos*(pos+1)/2 >= n){
			pos--;
		}
		long long ans = n - (pos*(pos+1)/2);
		ans %= 9;
		if(ans == 0){
			printf("9\n");
		}
		else{
			printf("%d\n",ans);
		}	
	}
	return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值