AC情况:
异或(xor) | 数学游戏(math) | 数学游戏(math) | 数字串(string) |
——(AC) | ——(AC) | ——(AC) | —— |
根本没做
异或(xor)
题意:
现在有n个长度为m的二进制数 a1∼an,问你:a1xora2 xor ...... xor an的二进制表示是什么?
题解:模拟
代码:
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
int main(){
string ans;
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++){
string s;
cin>>s;
if(i==1) ans=s;
else{
for(int i=0;i<m;i++){
ans[i]=(ans[i]-'0')^(s[i]-'0')+'0';
}
}
}
for(int i=0;i<m;i++){
cout<<ans[i];
}
return 0;
}
数学游戏(math)
题意:
现在有⼀个函数表示f(d) 的十进制表示下所有的数字之和,例如:f(432)=4+3+2=9
现在又有⼀个函数g(x) ,g(x)的计算方法为,枚举x的所有约数d ,然后算出x^d × f(d),再把这些数值加起来即为g(x)的值,具体来说:
g(x)=∑d∣xx^d×f(d)
求出g(1)+g(1)+⋅⋅⋅+g(n)
由于结果可能很大,你只需要输出结果对 109+7109+7取模的值就行。
题解:
先把从 1 到 n所有的 f ( i ) 都求出来。
类似于埃氏筛法
先从1遍历到n,找出i的所有倍数,那么i就一定是g[ij]的一个约数,
g[ij]累加ij^i*f[i]
取余的性质:(对除法不适用)
(a+b)%c=(a%c+b%c)%c
(a*b)%c=(a%c*b%c)%c
代码:
#include <bits/stdc++.h>
using namespace std;
const int ma = 1000000007;
long long ys[1000000],f[1000001],g[1000001];
int ksm(long long x, int b) {
long long a=1;
while(b) {
if(b%2==1)
a=a*x%ma;
b/=2;
x=x*x%ma;
}
return a;
}
int main(){
for(int i=1;i<=1e6;i++){
long long k=i;
long long sum=0;
while(k!=0){
sum+=k%10;
k/=10;
}
f[i]=sum;
}
long long n;
cin >> n;
long long ans = 0;
for (long long i = 1; i <= n; i++) {
for(long long j=1;i*j<=n;j++){
g[i*j]=(g[i*j]%ma+(ksm(i*j,i)%ma*f[i]%ma)%ma%ma)%ma;
}
}
for(long long i=1;i<=n;i++){
ans=(ans%ma+g[i]%ma)%ma;
}
cout<<ans<<endl;
return 0;
}
交换(swap)
题意:
可以将⼀个数的十进制表示下任意两个数位调换位置,但是需要保证调换后数字不包含前导0,
现在有n个数字a1∼an,每次可以任意选择一个数字(选过的可以再次选),将这个数字的任意符合要求的两位调换位置,他最多可以做k次操作,问经过了不超过从k次操作后,最小的ai最大可能是多少?
题解:
代码:
二分查找临界值,保证所有数一共进行 k次操作后都可以达到临界值及以上。
change函数:对数字 n进行一次操作。从最高位到最低位寻找第一个可以被替换的位替换的位,把它改成后面最大的数字,然后替换掉后面的那个大数字的位。
check函数:判断临界值mid是否满足情况,即所有的数一共进行 k次操作。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int maxn=1e6+10;
int a[maxn],b[maxn];
int n,k;
int change(int n) {
priority_queue<int> q;
queue<int> Q;
int m = n, a[15], cnt = 0;
while (m) {
q.push(m % 10);
a[++cnt] = m % 10;
m /= 10;
}
int res = 0, flag = -1, ch;
for (int i = cnt; i >= 1; i--) {
if (a[i] == q.top()) q.pop();
if (a[i] < q.top() && flag == -1) {
ch = a[i];
a[i] = q.top();
flag = q.top();
}
else if (flag != -1 && a[i] == flag && a[i - 1] != a[i]) {
a[i] = ch;
break;
}
}
for (int i = cnt; i >= 1; i--)
res = res * 10 + a[i];
return res;
}
bool check(int mid) {
int had = k;
for (int i = 1; i <= n; i++) b[i] = a[i];
for (int i = 1; i <= n; i++) {
while (b[i] < mid && b[i] != change(b[i]) && had > 0) {
b[i] = change(b[i]);
had--;
}
if (b[i] < mid) return false;
}
return true;
}
int main() {
cin >> n >> k;
for (int i = 1; i <= n; i++)
cin >> a[i];
int l = 1, r = 1e9 + 10, mid, ans = 0;
while (l <= r) {
mid = (l + r) / 2;
if (check(mid)) {
ans = max(ans, mid);
l = mid + 1;
} else {
r = mid - 1;
}
}
cout << ans;
return 0;
}
总结:
算法还应熟练掌握,尤其是二分