这应该是一个水题吧,,看学长们写的都好轻松的样子,不过我自己写的时候遇到了一个小问题,因为数据范围很大在运算的时候很有可能出现数据溢出的现象。
写的时候所有变量都采用的long long 型,尽量防止了数据范围不够。
题目大意:
给定一个整数w代表总价值上限
S(x)表示整数x的位数,一个整数x的价值是S(x)*k,k是给定的一个单位价值(整数每有一位价值就加上k)
m是整个整数列的起始项,求总价值不超过w的以m开头的连续递增整数列的最大长度
大致思路:
对于一个整数m,用一个函数digit(m)求它的位数
由于求的是总长度,以 cnt 来统计加入的整数数量,由于m在一定的连续范围内位数不变,也就是说,在m的位数增加之前,这一段整数的价值都是一样的,那么每次处理时处理一段整数。
Result : Accepted Memory : 0 KB Time : 15 ms
/*
* Author : Gatevin
* Time : 2014.4.9 19:28
* Problem : CodeForces 373B Making Sequences is Fun
* Tag : math
*/
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long lint;
lint w,m,k;
lint pow(lint base, lint y)
{
lint tmp = 1;
for(lint i = 1; i <= y; i++)
{
tmp *= base;
}
return tmp;
}
lint digit(lint x)//x的位数
{
lint a = 1;
while(pow(10,a) <= x)
{
a++;
}
return a;
}
lint remain(lint m)//m到下一进位的整数的数量
{
lint a = 1;
while(pow(10,a) <= m)
{
a++;
}
return pow(10,a) - m;
}
lint decrease(lint w, lint many, lint d, lint k)//这是类似于快速幂的一个想法,有效防止了数据溢出
{
lint a = 1;
while(many)
{
if(many&1)
{
w -= d*k*a;
}
many >>= 1;//类似于整数的快速幂,和数字逻辑里的8421码原理有点像
a *= 2;
}
return w;
}
int main()
{
cin>>w>>m>>k;
lint cnt = 0;
while(w >= digit(m)*k)//当价值w足以满足下一个整数
{
lint tmp = w/(digit(m)*k);//接下来可以有多少个这样位数的整数
if(tmp < remain(m))
{
w = decrease(w,tmp,digit(m),k);//这里如果改成减去tmp*digit(m)*k会出现数据溢出,,交的时候会在test13上wa掉了
m += tmp;
cnt += tmp;
}
else
{
w = decrease(w,remain(m),digit(m),k);
cnt += remain(m);
m = pow(10,digit(m));
}
}
cout<<cnt;
return 0;
}
PS : 坑爹的马原课,,,,,