网易笔试 0923
记错了开考时间导致三点10分才开始答题。时间不够了,就AC了前三道,第四题全输出1骗了14.29%。
第一题给定一个长度为n的数组下标从0到n-1,然后第 i 和第(i+2)%n可以交换,问任意次交换后,能否使得数组不严格单调递增。
方法是先判n是否是奇数,是奇数那所有位置之间都可以交换,为Yes,为偶数就是分奇数位和偶数位排序然后比较是否后一位大于前一位。
#include <bits/stdc++.h>
#include <cstdio>
using namespace std;
const int N = 1e5 + 20;
int n;
int a[N], b[N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t;
cin >> t;
while (t--)
{
cin >> n;
for (int i = 0; i < n; ++i)
cin >> ((i + 1) % 2 ? a[i / 2] : b[i / 2]);
if (n % 2)
{
puts("YES");
continue;
}
sort(a, a + n / 2);
sort(b, b + n / 2);
int flag = 1;
for (int i = 0; i < n / 2 - 1; ++i)
if (a[i] > b[i] || a[i + 1] < b[i])
{
flag = 0;
break;
}
if (a[n / 2 - 1] > b[n / 2 - 1])
flag = 0;
puts(flag ? "YES" : "NO");
}
return 0;
}
第二题给n个字符串,问有多少组字符串是类似的。“类似的”的定义是各个字母出现个数相同。比如aabbd和abadb
方法是哈希,然后在处理第i个字符串时,统计之前有多少字符串是与其类似的。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MOD = 19260817;
const ll INF = 1e18 + 7;
int n;
ll ans;
string s;
map<ll, int> mp;
int a[30];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n;
while (n--)
{
cin >> s;
for (auto p : s)
++a[p - 'a'];
ll tot = 0;
for (int i = 0; i <= 25; ++i)
tot = (tot * MOD + a[i]) % INF;
if (mp.count(tot))
ans += mp[tot], ++mp[tot];
else
mp.insert({tot, 1});
for (auto p : s)
--a[p - 'a'];
}
cout << ans << endl;
}
第三题问给定数组的所有子序列平均数之和。
方式是算每个数字对结果的贡献,比如[1,2,3,4]。1贡献为1的有一个,[1]。1贡献为1/2的有三个,[1,2],[1,3],[1,4]。1贡献为1/3的有3个,贡献为1/4的有1个。就是C^{i}_{n-1} / i+1,其中 i 从1遍历到n-1。然后 p / q 要转变成 p * q ^ {MOD - 2} 。
#include <bits/stdc++.h>
#include <cstdio>
using namespace std;
typedef long long ll;
const ll INF = 1e9 + 7;
const int N = 1e5 + 20;
int n;
int a[N];
ll qpow(ll x, ll y)
{
ll res = 1;
while(y)
{
if(y&1) res=res*x%INF;
x=x*x%INF;
y>>=1;
}
return res;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n;
ll tot = 0;
for(int i=1;i<=n;++i)
{
cin >> a[i];
tot += a[i];
}
tot %= INF;
ll val = 1, sum = 1, up = n - 1, down = 1;
for(int i=2;i<=n;++i)
{
sum = sum * up % INF;
sum = sum * qpow(down, INF - 2) % INF;
up--;
down++;
// cout << sum << ' ' << sum * 1.0 / i << endl;
val = (val + sum * qpow(i, INF - 2) % INF) % INF;
}
cout << val * tot % INF << endl;
return 0;
}
// 64 位输出请用 printf("%lld")
第四题是给定一棵n个节点的树,q次询问。每次询问一个点集,问多少个简单路径可以覆盖该点集。
受HDU5758启发。每次询问的时候构建一个虚树,答案为(虚树叶子数目+1)/2。如果根只有一个儿子时,也视为一个叶子。因为叶子不可能被不为它为端点的简单路径覆盖,所以叶子必定要是简单路径端点之一。
#网易#
查看9道真题和解析