2024.09.08小红书
1. 机器人走网格
小红书的冒险家们!今天,我们要进入一个充满挑战的高科技迷言。这是一张由小红书科技部最新研发的网格地图,每个格子都营着秘密一它们内置了自动滑行带!这些
滑行带会让所有进入它们的机器人自动翻一个特定方向滑行。
网格地图每个格子都藏着秘密一它们内置了自动滑行带!这些滑行带会让所有进入它们的机器人自动朝一个特定方向滑行。
具体来说,一张n*m的网格地图,左上角为(1,1),右下角为(n,m),每个格子有一个滑行带,前进方向为L,R,U,D,分别表示左右上下四个方向前进。
机器人走出地图后就会毁坏,一个格子可以容纳多个机器人。
第0时刻,每个位置都有一个机器人,问:第10^8时刻,地图上还剩下多少个机器人?
有循环的会进行保留
int main() {
int n,m;
cin>>n>>m;
int dir[4][2] = {{0,-1},{0,1},{-1,0},{1,0}};
map<char,int> mp = {{'L',0},{'R',1},{'U',2},{'D',3}};
vector<vector<int>> grid(n,vector<int>(m));
vector<vector<int>> flag(n,vector<int>(m));//0表示还没有遍历过,1是循环,-1不是
char c;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
cin>>c;
grid[i][j] = mp[c];
}
}
function<bool(int,int,int)> dfs = [&](int x,int y,int id)->bool{
if(flag[x][y]>0) return true;
if(flag[x][y]==-1) return false;
int nx = x+dir[grid[x][y]][0];
int ny = y+dir[grid[x][y]][1];
if(nx<0||ny<0||nx==n||ny==m) return false;
//边界条件
flag[x][y] = id;
if(flag[nx][ny]==id)
return true;
if(dfs(nx,ny,id))
return true;
flag[x][y] = -1;
return false;
};
int res = 0;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(dfs(i,j,i*m+j+1)) res++;
}
}
cout<<res<<endl;
return 0;
}
2. 小苯到的区间和之和
小苯有一个长度为n的数组a,他定义了一个函数
\(f:f(l, r)=\sum_{k=l}^{r} a_{k}\)
即f(l,r)表示数组a在[l,r]这一段区间的区间和。现在小苯有一个重新任意排列数组a的机会,他想要最小化\(\sum_{r=l}^{n}\) f(l, r) 即最小化所有区间对应f的值之和,请你帮他算算最小的这个值吧。
贡献法的思维题
int main(int argc, char *argv[]) {
vector<int> nums;
int num;
while(cin>>num){
nums.push_back(num);
if(cin.get()=='\n') break;
}
int n = nums.size();
sort(nums.begin(),nums.end());
vector<int> cnt(n);
for(int i=0;i<n;i++)
cnt[i] = (i+1)*(n-i-1);
sort(cnt.begin(),cnt.end(),greater<int>());
int res = 0;
for(int i=0;i<n;i++)
res+=nums[i]*cnt[i];
cout<<res;
return 0;
}
3. 小红的笔记精选
定义f(x)为×在二进制表示下的1的个数,例如f(7)=3,f(8)=1,f(9)=2.定义g(x)为第一个比x大的数字y,使得f(x)=f(y),
例如g(1)=2,g(2)=4,g(3)=5.小红书首页有n篇笔记,第i篇笔记的点赞数量为ai,我们希望从中挑选出一些笔记,构造一个长度为m的精选队列b1,b2,...,bm·在这里,
精选队列满足:对于所有的j∈[2,m],都有b_{j}=g(b_{j-1}) 。当然,精选队列越长越好,请你最大化其长度m,并输出之。
排序+动态规划+位运算思维题
ll anext(ll a){//找a的下一个更大满足条件值
if (a == 0)
return 0;
ll base = 1;
while ((base & a) == 0) base <<= 1;
while ((base & a) == base) base <<= 1;
a += base >> 1;
ll b = a % base;
a -= b;
while (b > 0 && b % 2 == 0)
b >>= 1;
return a + b;
}
bool cmp(ll a, ll b) //按1的位数排序,相当于拆分掉不同1位数的数组
{
if (__builtin_popcountll(a) != __builtin_popcountll(b))
return __builtin_popcountll(a) < __builtin_popcountll(b);
return a < b;
}
int main(int argc, char *argv[]) {
int n;
cin >> n;
vector<ll> a(n);
for (int i = 0; i < n; i++)
cin >> a[i];
sort(a.begin(), a.end(), cmp);
ll ans = 1, cnt = 1;
for (int i = 1; i < n; i++){
if (a[i] == anext(a[i - 1])) cnt++;
else if (a[i] == a[i - 1]) continue;
else{
ans = max(ans, cnt);
cnt = 1;
}
}
ans = max(ans, cnt);
cout<< ans << endl;
return 0;
}