A.https://ac.nowcoder.com/acm/contest/4853/A
思路:考虑位运算&的特性 只有两者都为1才会对答案有贡献 且 对答案贡献的值为 1 << k 其中k是当前1所在二进制下的位数 所以考虑预处理每一个位的1出现的次数 其中对每一位都会遍历n*n次 所以每一位对答案的贡献就是 a[i]a[i](1 << i) a[i]为当前位置1的个数
#include <bits/stdc++.h>
using namespace std;
#define LL long long
int main()
{
int n;
cin >> n;
LL a[35] = {0};
for(int i = 0;i < n;i ++)
{
int x;
cin >> x;
int k = 0;
while(x)
{
a[k ++] += x%2 ;
x /= 2;
}
}
LL sum = 0;
for(int i = 0;i <= 32;i ++)
{
sum += a[i]*a[i]*(1<<i);
}
printf("%lld\n",sum);
return 0;
}
B.https://ac.nowcoder.com/acm/contest/4853/B
题意:给出n个点 用这n个点构造三角形 问这些三角形的周长是多少 数据保证合法
思路:我们从边考虑 组成一个三角形需要三条边 且 必须要三条边 所以每条边只能被选 n - 2次 所以每条边对答案的贡献 就是曼哈顿距离* 出现的次数为n-2次 然后暴力计算和即可 记得开LL
#include <bits/stdc++.h>
using namespace std;
#define LL long long
const int mod = 998244353;
LL a[3005][2];
int main()
{
int n;
cin >> n;
for(int i = 0;i < n;i ++)
{
cin >> a[i][0] >> a[i][1];
}
LL sum = 0;
for(int i = 0;i < n - 1;i ++)
{
for(int j = i + 1;j < n;j ++)
{
sum += (((abs(a[i][0] - a[j][0])) + abs(a[i][1] - a[j][1]))*(n - 2))%mod;
sum %= mod;
}
}
printf("%lld\n",sum%mod);
return 0;
}
C.https://ac.nowcoder.com/acm/contest/4853/C
题意:给出长度为n的字符串 求有少长度为k的不同子序列
思路:dp肯定是没跑了 用i, j , k 来表示 前i个字符 长度为j 以字符’a’ + k结尾的子串 dp的值为字符串的数量
如果s[i] == ‘a’ + k 则构造出新的字符串 否则 则从上个状态转移过来
#include <bits/stdc++.h>
using namespace std;
#define LL long long
const int mod = 1e9 + 7,N = 1e3 + 5;
LL dp[N][N][30];///前i个字符 长度为j的 以'a' + k 为结尾的字符串
int main()
{
int n , m;
string s;
cin >> n >> m ;
cin >> s;
if(!m)
{
cout << 1;
return 0;
}
for(int i = 1;i <= n;i ++)
{
dp[i][1][s[i - 1] - 'a'] = 1;
for(int j = 1;j <= m;j ++)
{
for(int k = 0;k < 26;k ++)
{
if(s[i - 1] - 'a' == k)
{
for(int kk = 0; kk < 26 ;kk ++)
{
dp[i][j][k] += dp[i - 1][j - 1][kk];
dp[i][j][k] %= mod;
}
}
else
{
dp[i][j][k] += dp[i - 1][j][k];
dp[i][j][k] %= mod;
}
}
}
}
LL res = 0;
for(int i = 0;i < 26;i ++)
res += dp[n][m][i],res %= mod;
printf("%lld\n",res);
return 0;
}
D.待补