0904淘天笔试
第一题:(100)
(1e5次查询,问n(1e18)是不是立方数和平方数。
两次二分或者立方数先打表,平方数二分、
(第一题跟2、3题分开的,做完2、3后没法复制到粘贴板了)
第二题:(100)
求[0,10^r]中各个数位和为y的总数(1<=r,y<=1000)
简单的数位dp
#include "bits/stdc++.h" using namespace std; const int mod = 1e9 + 7; int main() { int r, y; cin >> r >> y; vector<vector<int> > dp(r + 1, vector(y + 1, -1)); auto dfs = [&](auto&& dfs, int index, int sum)->int{ if (sum == y && index <= r) { dp[index][sum] = 1; return 1; } if ((r - index) * 9 + sum < y) { dp[index][sum] = 0; return 0; } if (dp[index][sum] != -1) return dp[index][sum]; int ans = 0; for (int i = 0; i <= 9; i++) { if (sum + i <= y) ans = (ans + dfs(dfs, index + 1, sum + i)) % mod; } dp[index][sum] = ans; return ans; }; int ans = dfs(dfs, 0, 0); if (y == 1) ans++; cout << ans << endl; return 0; }
第三题:(50)
给一个字符串表示泡泡机('-')、泡泡('o'),空地('?')(最左边最右边为墙壁)
每秒泡泡机往左右各出一个泡泡,当泡泡机之间或者泡泡机与墙壁之间最下面都充满泡泡时,再吐出的泡泡会漂浮到空中。问多少秒时空中至少有k个泡泡。(字符串长度1e5,1<=k<=1e9)
比如"??-??-??"
第一秒:"?o-oo-o?" 0个空中
第二秒:"oo-[o,o][o,o]-oo" 2个空中
第三秒:"[o,o]o-[o,o,o][o,o,o]-o[o,o]" 6个空中
思路是前缀和+模拟+贪心
用一个vector存各个泡泡机的位置,用一个前缀和统计初始泡泡的前缀和
用map统计每个时间点开始飞向空中泡泡的数目。
然后分别遍历泡泡机之间或者泡泡机与墙壁的非泡泡空地数目(前缀和求解),设置为count。
对于泡泡机与墙壁之间,mp[count+1]++
泡泡机之间:左边的是mp[count/2+1]++,右边的是:mp[(count-1)/2+1]++
然后遍历map,用sum表示当前空中泡泡数目,cnt表示之前单位时间能够产生的泡泡数目,t表示上一次遍历的时间
用iter表示map的当前迭代值
int slove(){ int k; map<int,int> mp; int sum = 0,cnt = 0,t=0; for(auto iter:mp){ sum += cnt*(iter.first-t)+iter.second; cnt += iter.second; t = iter.first; if(sum >= k) return t; } return t + ceil(double(k-sum)/cnt); }#淘天笔试##25秋招##笔试#