原题: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自然只能为10if ((j * (v[i] < 10 ? 10 : 28) + v[i]) % 36 == 0) {//若为0,说明找到余数,有几个数%36=j,ans就加几ans += yushu[j];}}//把当前的数%36后存入yushu中,防止把一个数用两次//同时也可看出这里没有计算它们反过来拼接的情况,所以后面要反转数组v如输入数据为6,3,这里只计算了63,没有算36yushu[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,没有算36f(v);//反转数组reverse(v.begin(), v.end());f(v);cout << ans << "\n";
}