长整数拼接后求余数

原题:2024牛客寒假算法基础集训营3   M题

 

方法一:

        用递归进行长整数除法,暴力寻找,但是会超时

#include <bits/stdc++.h>
using namespace std;
bool f(string &s, int ans,int count) {
    if (count > s.size()) {
        if (ans % 36 == 0)return true;
        return false;
    }
    bool b = false;
    ans = ans * 10 + (s[count - 1] - '0');
    if (ans < 36) b = f(s, ans, count + 1);
    else {
        ans = ans % 36;
        b = f(s, ans, count + 1);
    }
    return b;
}
int main() {
    int n;
    cin >> n;
    vector<long long>v(n, 0);
    for (int i = 0; i < n; i++)cin >> v[i];
    long long ans = 0;
    for (int i = 0; i < n - 1; i++) {
        for (int j = i + 1; j < n; j++) {
            string temp1 = to_string(v[i]) + to_string(v[j]);
            string temp2 = to_string(v[j]) + to_string(v[i]);
            if ((temp1[temp1.size() - 1] - '0') % 2 == 0) {
                if (f(temp1, 0, 1))ans++;
            }
            if ((temp2[temp2.size() - 1] - '0') % 2 == 0) {
                if (f(temp2, 0, 1))ans++;
            }
        }
    }
    cout << ans << "\n";
}

方法二:

        用余数解决。因为设x,当x>=2时,10^x % 36恒等于28,所以当两个整数 p , q 拼接后,假如整数 q 位数大于等于两位,其余数为 ((p%36)*28 + q)%36。

        可以举个例子:假如两个数为15, 105,拼接后为15105,15105%36=21

15105=15*1000+105

(15*1000+105)%36=[(15%36*1000%36)+105]%36=21

核心代码:

// v存放输入的正整数
void f(vector<ll>& v) {
    // 记录每个数据对36取模的值
	vector<ll>yushu(36, 0);
	for (int i = 0; i < v.size(); i++) {
		for (int j = 0; j < 36; j++) {
            // 把余数j对应的整数拼接到v[i]前面
            // 当v[i]<10时,10%36自然只能为10
			if ((j * (v[i] < 10 ? 10 : 28) + v[i]) % 36 == 0) {
                //若为0,说明找到余数,有几个数%36=j,ans就加几
				ans += yushu[j];
			}
		}
        //把当前的数%36后存入yushu中,防止把一个数用两次
        //同时也可看出这里没有计算它们反过来拼接的情况,所以后面要反转数组v
        如输入数据为6,3,这里只计算了63,没有算36
		yushu[v[i] % 36]++;
	}
}

完整代码:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int n;
ll ans = 0;
void f(vector<ll>& v) {
	vector<ll>yushu(36, 0);
	for (int i = 0; i < v.size(); i++) {
		for (int j = 0; j < 36; j++) {
			if ((j * (v[i] < 10 ? 10 : 28) + v[i]) % 36 == 0) {
				ans += yushu[j];
			}
		}
		yushu[v[i] % 36]++;
	}
}
int main() {
	cin >> n;
	vector<ll>v(n, 0);
	for (int i = 0; i < n; i++)cin >> v[i];
    //这里没有计算它们反过来拼接的情况,所以后面要reverse数组v
    //如输入数据为6,3,这里只计算了63,没有算36
	f(v);
    //反转数组
	reverse(v.begin(), v.end());
	f(v);
	cout << ans << "\n";
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值