A. Math loser
首先如果一个
和
相同,那么必然不满足条件,所以我们可以排除
为素数的情况。
那么我们只需要筛出所有的素数,那么一个数的
和
必然是相邻的素数,那么我们就枚举
和
,来按区间来统计答案惹。
现在考虑一个简单容斥,假如我们要计算的是只能
或
整除的数的个数,那么我们需要计算出能被
整除的数的个数,能被
整除的数的个数,然后减去
倍的同时能被
和
整除的数个数即可。
既然能求出个数,那么按等差数列扩展一下就是求和了。
#define others
#ifdef poj
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#endif // poj
#ifdef others
#include <bits/stdc++.h>
#endif // others
//#define file
#define all(x) x.begin(), x.end()
using namespace std;
#define eps 1e-8
const double pi = acos(-1.0);
typedef long long LL;
typedef unsigned long long ULL;
void umax(int &a, int b) {
a = max(a, b);
}
void umin(int &a, int b) {
a = min(a, b);
}
int dcmp(double x) {
return fabs(x) <= eps?0:(x > 0?1:-1);
}
void file() {
freopen("data_in.txt", "r", stdin);
freopen("data_out.txt", "w", stdout);
}
namespace Solver {
const int maxn = 11000000;
int tag[maxn];
vector<int> G;
LL n;
void shai() {
for(int i = 2; i < maxn; i++) {
if(!tag[i]) G.push_back(i);
for(int j = 0; j < G.size() && i * G[j] < maxn; j++) {
tag[i*G[j]] = 1;
if(i % G[j] == 0) break;
}
}
}
LL cal(LL x, LL v) {
LL sz = x / v;
return sz * (sz + 1) / 2 * v;
}
LL gao(LL l, LL r, LL v) {
return cal(r, v) - cal(l-1, v);
}
void solve() {
shai();
int t;
scanf("%d", &t);
while(t--) {
scanf("%lld", &n);
LL ans = 0;
for(int i = 0; i < G.size() - 1; i++) {
LL ls = 1LL * G[i] * G[i], rs = 1LL * G[i+1] * G[i+1];
if(ls > n) break;
rs--;
rs = min(rs, n);
ls++;
ans += gao(ls, rs, G[i]) + gao(ls, rs, G[i+1]) - 2LL * gao(ls, rs, 1LL*G[i]*G[i+1]);
}
printf("%lld\n", ans);
}
}
};
//1259187438574927161
int main() {
// file();
Solver::solve();
return 0;
}
这里提供一个优雅的暴力,每次跳着素数找,弄出所有的优雅数,因为优雅数的个数很少,所以可过。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 3e6+3;
bool vis[maxn];
vector<LL > a;
void init()
{
memset(vis, false, sizeof vis);
for(int i=2; i<maxn; i++)
{
if(vis[i]) continue;
a.push_back(i);
for(int j = 2; i*j<maxn; j++)
vis[i*j] = true;
}
return;
}
int main()
{
init();
int T;
LL n;
scanf("%d", &T);
while(T--)
{
LL sum = 0;
scanf("%lld", &n);
for(int i=0; i<a.size(); i++)
{
LL l = a[i]*a[i];
LL r = min(n+1, a[i+1]*a[i+1]);
if(l>n) break;
for(int k=a[i]+1; k*a[i]<r; k++){
if(k!=a[i+1] && k!=a[i]) {
sum += k*a[i];
}
}
for(int k=r/a[i+1]; k*a[i+1]>l; k--){
if(k!=a[i] && k!=a[i+1]) {
sum += k*a[i+1];
}
}
}
printf("%lld\n", sum);
}
return 0;
}
B. A man with iron bone
签到题,模拟题,“我就是退学,倒贴钱,也要坚持打ACM”“嘿嘿。退坑真爽”。
#define others
#ifdef poj
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#endif // poj
#ifdef others
#include <bits/stdc++.h>
#endif // others
//#define file
#define all(x) x.begin(), x.end()
using namespace std;
const double pi = acos(-1.0);
typedef long long LL;
typedef unsigned long long ULL;
void umax(int &a, int b) {
a = max(a, b);
}
void umin(int &a, int b) {
a = min(a, b);
}
void file() {
freopen("data_in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
}
namespace Solver {
using namespace std;
int t;
void solve() {
// file();
scanf("%d", &t);
while(t--) {
string s;
cin >> s;
int now = 1;
for(int i = 0; i < s.size(); i++) {
if(1 <= now && now <= 3 && s[i] == 'D') now++;
else if(now >= 4 && now <= 5 && s[i] == 'U') now++;
else if(now == 6 && s[i] == 'L') now++;
else if(now == 7 && s[i] == 'U') now++;
else if(now == 8 && s[i] == 'R') now++;
}
if(now == 9) {
puts("zhen xiang!");
}
else {
puts("wangjingze, e si, siwaibian, tiaoxiaqu!");
}
}
}
};
int main() {
// file();
Solver::solve();
return 0;
}
/*
10
DDDWWLUR
*/
C. Delete substring
这个是我当时看错牛客一个题目的题意得来的
首先删的多肯定可以满足要求,单调性比较显然,因此可以二分。
枚举删掉的子串,可以用前缀和和后缀和快速得到新串的变化次数。
因此二分 + 前缀和后缀和就可以了。
当然也有O(n)的做法。
#define others
#ifdef poj
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#endif // poj
#ifdef others
#include <bits/stdc++.h>
#endif // others
//#define file
#define all(x) x.begin(), x.end()
using namespace std;
#define eps 1e-8
const double pi = acos(-1.0);
typedef long long LL;
typedef unsigned long long ULL;
void umax(int &a, int b) {
a = max(a, b);
}
void umin(int &a, int b) {
a = min(a, b);
}
int dcmp(double x) {
return fabs(x) <= eps?0:(x > 0?1:-1);
}
void file() {
freopen("data_in.txt", "r", stdin);
freopen("data_out.txt", "w", stdout);
}
namespace solver {
int n, m;
const int maxn = 1100000;
int pre[maxn], suf[maxn];
char str[maxn];
bool check(int x) {
if(x > n) return 1;
if(suf[x+1] <= m) return 1;
for(int i = 2; i <= n - 1; i++) {
if(i + x - 1 > n) continue;
int t = i + x - 1;
if(pre[i-1] + suf[t+1] + (str[i-1] != str[t + 1]) <= m) return 1;
}
if(pre[n-x] <= m) return 1;
return 0;
}
void solve() {
scanf("%d%d%s", &n, &m, str + 1);
bool isok = 1;
for(int i = 1; i <= n; i++)
if(str[i] != 'b')
isok = 0;
if(isok) {
puts("0");
return ;
}
for(int i = 2; i <= n; i++)
pre[i] = pre[i-1] + (str[i] != str[i-1]);
if(pre[n] <= m) {
cout<<n<<endl;
return ;
}
for(int i = n - 1; i >= 1; i--)
suf[i] = suf[i+1] + (str[i] != str[i+1]);
int l = 0, r = maxn - 1, m;
while(l < r) {
m = l + r >> 1;
if(check(m)) r = m;
else l = m + 1;
}
cout<<n - l<<endl;
}
}
int main() {
// file();
int t;
scanf("%d", &t);
while(t--) solver::solve();
return 0;
}
D.Guess
签到题,就是想看看大家对题目的理解能力(能不能坑到大家)。
#include <iostream>
using namespace std;
int main(){
puts("a digit in [0, 9], but i don't know which one is correct.");
return 0;
}