您的位置:首页 > 其它

第十二届北航程序设计竞赛预赛

2016-12-12 12:36 337 查看
https://biancheng.love/contest-ng/index.html#/123/problems

题目链接

A、C看懂题意就好了。

G题,贪心,最大的数肯定要越高位越好,所以尽量放1,剩3就放7,次大就调过来。特判下4没了。

D题,求出每个点需要推到的概率然后加起来。

M题,贪心可得,大乘小对应起来,然后求次数,就用类似求一个个环,假如不对应的环就需要环内点个数-1次来交换。因为假如环内有x个点,你交换x-1次,最后一个也会排好序了

L题,用几个数组维护一下每个点四个方向最远能到达的点,然后求T就枚举中间那个点,L就枚举左下角那个点,求S就枚举最上面的两个点,n^3

F题,一个多边形,它夹角对应的都要放在整数点上,那只能是正方形了,多边形面积是一个n·[(a^2)/4]·cot(π/n),然后cot好像只有几个特殊点才是有理数吧,如果坐标都在整数点上,那面积肯定可以割割割,反正是个有理数,大概是这样证明的。所以问题就变成从n个点选4个能否组成正方形,把全部点hash起来,然后枚举正方形任意两个点,再判断另外两个点是否存在就行了,复杂度是n^2,光看数据以为会T就加了个读入挂,不知道有没有其他做法。

K题,我们先把这个东西的类似层次遍历的图画一画,就会发现,其实答案会是某层状态最多的方案数量,然后题目就转化成了将若干个数分成n堆,每一堆都有不同的限制di。然后就是dp搞,dp[i][j]表示前i堆分了j个的方案数,然后dp[i][j] = sum(dp[i-1][k])(0<=k<=j&&j-k<di)了为什么小于,因为每一堆上原本就有一个1的,然后求max(dp
[k])(0<k<若干个数)就是答案了。

B题,首先我瞎做的时候是毫无思路的,于是就自己做起了小学加法题,然后发现每进位一次,原本的数位和就会-9,好了,然后就开始搞了,从L+到R,进位M次,我们需要先能快速求出0-x之间所有数的数位和,这个我们可以用类似拆位来递归下去,先预处理出0-(10^k - 1)之间的数位和,这个比较简单

sum[0] = 0,sum[i] = sum[i-1]*10 + 45*10^(i-1);

那这样我们就可以拆位算下去了,比如求434

我们先算

0 - 99 = sum[2]

100 - 199 = 1 * 10^2 + sum[2]

200 - 299 = 2 * 10^2 + sum[2]

300 - 399 = 3 * 10^2 + sum[2]

400 - 434 我们可以把最前面那个4的贡献单独求出来 = 4 * 35

然后再 + 递归(34)

会求这个之后,我们先暴力求一下最高上界会是多少。。算出来发现挺小的,于是我就把上界设为3e7了,

二分一下R

变成(Cnt(R) - Cnt(L-1) - 暴力求数位和((L+R)*(R-L+1)/2) )/ 9这个就是进位次数了,然后把R逼近上界就行了

#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <cstring>
#include <vector>
#include <string>
#include <stack>
#include <set>
#include <map>
#include <iostream>
#include <algorithm>
using namespace std;
#define MP make_pair
#define PB push_back
typedef long long LL;
typedef pair<int, int> Pii;
const int inf = 0x3f3f3f3f;
const LL INF = (1uLL << 63) - 1;
const LL mod = 1000000007;
const int N = 1e5 + 5;
const double Pi = acos(-1.0);
const int maxn = 2e6 + 5;
LL sum[15];
int gao(LL a) {
int res = 0;
while(a) {
res += a % 10;
a /= 10;
}
return res;
}
int Cnt(int n) {
if(n < 10)return n * (n + 1) / 2;
int d = log10(n);
int p = ceil(pow(10, d));
int tst = n / p;
return tst * sum[d] + (tst * (tst - 1) / 2) * p + tst * (1 + n % p) + Cnt(n % p);
}
int upcnt(LL &res , LL b) {
LL c = res;
res += b;
int up = 0;
int d = 0;
while(b || c) {
if( (d = d + b % 10 + c % 10) > 9 )up++;
d /= 10;
b /= 10;
c /= 10;
}
return up;
}
LL pai(LL l, LL m) {
LL res = 0;
int g = 0;
for(LL i = l ; ; i++) {
g += upcnt(res, i);
if(g > m) {
return res - i;
//return i-1;
}
}
}
int main() {
#ifdef local
freopen("in", "r", stdin);
#endif
for(int i = 1; i <= 10; i++) {
sum[i] = sum[i - 1] * 10 + 45 * ceil(pow(10, i - 1));
}
int T;
cin >> T;
while(T--) {
LL L, M;
cin >> L >> M;
int d = Cnt(L - 1);
int l = L , r = L + 2e7;
LL res = 0;
while(l <= r ) {
LL mid = ( l + r ) >> 1;
//  cout<<(mid + L) * (mid - L + 1) / 2<<endl;
int now = gao((mid + L) * (mid - L + 1) / 2);
int diff = Cnt(mid) - d - now;
diff /= 9;
if(diff <=  M) {
l = mid + 1;
res = (mid + L) * (mid - L + 1) / 2;
} else r = mid - 1;
}
cout << res << endl;
}

}


B
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐