KDY十一月月赛入门赛第一场补题报告

AC情况:

异或(xor)数学游戏(math)数学游戏(math)数字串(string)
——(AC)——(AC)——(AC)——

根本没做

异或(xor)

题意:

现在有n个长度为m的二进制数 a​1​​∼a​n​​,问你:a​1​​xora​2​​ xor ...... xor a​n​​的二进制表示是什么?

题解:模拟

代码:

#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∣x​​x^​d​​×f(d)

求出g(1)+g(1)+⋅⋅⋅+g(n) 

由于结果可能很大,你只需要输出结果对 109+710​9​​+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个数字a​1​​∼a​n​​,每次可以任意选择一个数字(选过的可以再次选),将这个数字的任意符合要求的两位调换位置,他最多可以做k次操作,问经过了不超过从k次操作后,最小的a​i​​最大可能是多少?

题解:

代码:

二分查找临界值,保证所有数一共进行 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;
}

总结:

算法还应熟练掌握,尤其是二分 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值