文章目录
- A. Rounding
- B. Proper Nutrition
- C. Phone Numbers
- D. Alarm Clock
- E. Squares and not squares
- F. Restoring the Expression
A. Rounding
- 题意
给你一个非负整数,需要你输出将其舍入到最接近的整数,且末尾是。
/**
  *@filename:A
  *@author: pursuit
  *@created: 2021-08-12 14:05
**/
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int N = 1e5 + 10;
const int P = 1e9 + 7;
const int INF = 0x3f3f3f3f;
int n;
void solve(){
    int temp = n % 10;
    if(temp >= 5){
        n = n / 10 * 10 + 10;
    }
    else{
        n = n / 10 * 10;
    }
    cout << n << endl;
}
int main(){
    cin >> n; 
    solve();
    return 0;
}- 解题思路
 取最低位判断是否即可,据此作出改变, 。 
- AC代码
B. Proper Nutrition
- 题意
 给你三个整数,找出是否存在 使得 。 
- 解题思路
 直接暴力即可,枚举即可确定 ,而 为 , 复杂度可以通过。 
- AC代码
/**
  *@filename:B
  *@author: pursuit
  *@created: 2021-08-12 14:08
**/
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int N = 1e5 + 10;
const int P = 1e9 + 7;
const int INF = 0x3f3f3f3f;
int n,a,b;
void solve(){
    int maxx = n / b;
    for(int i = 0; i <= maxx; ++ i){
        int temp = n - i * b;
        if(temp % a == 0){
            cout << "YES" << endl;
            cout << temp / a << " " << i << endl;
            return;
        }
    }
    cout << "NO" << endl;
}
int main(){ 
    cin >> n >> a >> b;
    solve();
    return 0;
}C. Phone Numbers
- 题意
 给你每个人的电话号码信息,需要你对每一个人的电话号码信息进行处理,即若甲的电话号码是甲的电话号码 的后缀,那么就删除 。按格式输出处理后的信息。 
- 解题思路
 好题。考察细节,对字符串的处理以及一些必要的数据存储技能。我们首先需要存储每个人的姓名以及电话信息,这里我们采用存储,同时我们需要确定每个人的编号方便索引存储位置以及需要通过编号来确定姓名,这里采用了两个 实现。当然,我们也可以只用一个结构体来实现存储。注意一定要判断每个人是否之前已经存储过了,若存储过直接在原地方存储即可。 
 处理好之后,我们来分析怎么删除,如果是 的后缀,那么第一点就是 。所以我们可以先对每个人的电话号码按长度大小排序,这样能保证长度要求。那么之后就是要比较是否相等了,根据 自然能索引到 在 中的起始判断位置,即使 ,故只需判断 即可。 
- AC代码
/**
  *@filename:C
  *@author: pursuit
  *@created: 2021-08-12 14:31
**/
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int N = 22 + 10;
const int P = 1e9 + 7;
const int INF = 0x3f3f3f3f;
int n,cnt;
map<int,string> p1;
map<string,int> p2;
vector<string> ans[N];
string s,num;
//按字符串长度排序。
bool cmp(string a,string b){
    return a.size() < b.size();
}
void solve(){
    cout << p2.size() << endl;
    for(int i = 1; i <= cnt; ++ i){
        //处理每个人的号码。 
        sort(ans[i].begin(),ans[i].end(),cmp);
        for(int j = 0; j < ans[i].size(); ++ j){
            string num1 = ans[i][j];
            for(int k = j + 1; k < ans[i].size(); ++ k){
                string num2 = ans[i][k];
                if(num2.substr(num2.size() - num1.size()) == num1){
                    ans[i].erase(ans[i].begin() + j);
                    j --;
                    break;
                }
            }
        }   
        cout << p1[i] << " " << ans[i].size() << " ";
        for(int j = 0; j < ans[i].size(); ++ j){
            cout << ans[i][j] << " ";
        }
        cout << endl;
    }
}
int main(){
    cin >> n;
    for(int i = 1; i <= n; ++ i){
        cin >> s;
        if(!p2[s]){
            p2[s] = ++ cnt;
            p1[cnt] = s;
        }
        int id = p2[s],tot;
        cin >> tot;
        while(tot -- ){
            cin >> num;
            ans[id].push_back(num);
        }
    } 
    solve();
    return 0;
}D. Alarm Clock
- 题意
 给你一个时钟,其响铃时间为 ,需要你至少关闭多少个闹钟才能使得连续 分钟响铃次数 。 
- 解题思路
 使劲贪即可。注意到,我们必然是时再关闭,且一定是关闭触发这个条件时刻的一些闹钟,使得响铃次数变成 ,至此题解。 
- AC代码
/**
  *@filename:D
  *@author: pursuit
  *@created: 2021-08-12 15:28
**/
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int N = 1e6 + 10;
const int P = 1e9 + 7;
const int INF = 0x3f3f3f3f;
int n,m,k,x;
int a[N],maxx;
ll cnt;
void solve(){
    ll ans = 0;
    for(int i = i; i <= maxx; ++ i){
        if(i < m)cnt += a[i];
        else cnt += (a[i] - a[i - m]);
        if(cnt >= k){
            ans += cnt - k + 1;
            a[i] -= (cnt - k + 1);
            cnt = k - 1;
        }
        //cout << cnt << endl;
    }
    printf("%lld\n", ans);
}
int main(){ 
    scanf("%d%d%d", &n, &m, &k);
    for(int i = 1; i <= n; ++ i){
        scanf("%d", &x);
        maxx = max(maxx,x);
        a[x] ++;
    }
    solve();
    return 0;
}E. Squares and not squares
- 题意
 给定个数,你可以对其中每个数进行 操作,问使得这 个数有 个非平方数和 个平方数的最少操作次数。 
- 解题思路
 对于平方数变非平方数,+1即可(0需要+2),对于非平方数变平方数,选择最近的那个即可。将这些数的消耗排序,取最小的即可。
- AC代码
/**
  *@filename:E
  *@author: pursuit
  *@created: 2021-08-12 15:39
**/
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int N = 2e5 + 10;
const int P = 1e9 + 7;
const int INF = 0x3f3f3f3f;
int n;
ll x;
ll a[N],b[N];
int cnta,cntb;
ll cal(ll *a,int x,int n){
    ll res = 0;
    sort(a + 1,a + 1 + n);
    for(int i = 1; i <= x; ++ i){
        //cout << a[i] << endl;
        res += a[i];
    }
    return res;
}
void solve(){
    if(cnta == cntb){
        puts("0");
    }
    else{
        printf("%lld\n",cnta > cntb ? cal(a,cnta - n / 2,cnta) : cal(b,cntb - n / 2,cntb));
    }
}
int main(){ 
    scanf("%d", &n);
    for(int i = 1; i <= n; ++ i){
        scanf("%lld", &x);
        int temp = sqrt(x);
        if(temp * temp == x){
            if(x)a[++cnta] = 1;
            else a[++cnta] = 2;
        }
        else{
            b[++cntb] = min((temp + 1) * (temp + 1) - x,x - temp * temp);
        }
    }
    solve();
    return 0;
}F. Restoring the Expression
- 题意
 给定一个数值字符串,需要你分割成 使得 不包含前导零,且 。 
- 解题思路
 注意到的范围,所以我们需要在 时间内解决。我们发现,只需要枚举 = 号的位置,而根据其合理性 ,那么确定了 ,则有4种可能。  
 所以实际上我们是可以在线性时间内完成字符串的分割的,关键在于判断,大数首先排除 ,那么有什么方法呢?这里引入 ,也叫散列值,就是将字符串映射成一个数值,一个数值代表一个字符串。字符串hash,【算法学习】字符串哈希(Hash),大家可以看一下一些 学习。于是如果我们比较字符串相等,那么可以直接比较它们的 ,这样就达到了 的字符串相等判断,即用空间换时间。字符串 需要我们确定 和 ,然后对应的 公式即为 ,对于此方法,我们需要将 和 取大一点,这样才能避免数值冲突。如果要获取字串的 值,那么其对应公式即为 )$ 
 那么这里还需提到的一点就是如何得到,就是直接散列值相加即可,因为每个值可以唯一代表一个字符串。 算法各种各样,能写出适合自己的 模板即可。 
- AC代码
/**
  *@filename:F
  *@author: pursuit
  *@created: 2021-08-12 15:55
**/
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int N = 1e6 + 10;
const int P = 1e9 + 7;
const int INF = 0x3f3f3f3f;
int n;
int base = 10;//base为基底,其代表了为几进制数。
ll Hash[N],p[N];
string s;  
//字符串hash,写法有很多种。
//不过思路都是一样的,就是要用唯一的数值确定一段字符串。所以也跟mod有关。
void init(){
    n = s.size();
    for(int i = 0; i < n; ++ i){
        Hash[i + 1] = (Hash[i] * base % P + s[i] - '0') % P;
    }
    p[0] = 1;//base ^ i
    for(int i = 0; i < n; ++ i){
        p[i + 1] = p[i] * base % P;
    }
}
int get(int l,int r){
    //获取[l,r]子串。
    if(r < 0 || l - 1 < 0 || r - l + 1 < 0)return 0;
    return (Hash[r] - Hash[l - 1] * p[r - l + 1] % P + P) % P;
}
bool check(int lenA,int lenB,int lenC){
    if(lenA > lenC || lenB > lenC)return false;
    if(lenA < 0 || lenB < 0)return false;
    if(s[lenA] == '0' && lenB != 1)return false;
    if(s[0] == '0' && lenA != 1)return false;
    if((get(1,lenA) + get(lenA + 1,lenA + lenB)) % P != get(lenA + lenB + 1,n)){
        return false;
    }
    return true;
}
void print(int lenA,int lenB,int lenC){
    for(int i = 0; i < lenA; ++ i){
        putchar(s[i]);
    }
    putchar('+');
    for(int i = lenA; i < lenA + lenB; ++ i){
        putchar(s[i]);
    }
    putchar('=');
    for(int i = lenA + lenB; i < n; ++ i){
        putchar(s[i]);
    }
}
void solve(){
    for(int lenC = 1; lenC < n; ++ lenC){
        if(s[n - lenC] == '0' && lenC > 1)continue;//排除前导0的情况。
        //cout << lenC << endl;
        if(check(lenC,n - 2 * lenC,lenC)){
            print(lenC,n - 2 * lenC,lenC);
            break;
        }
        else if(check(n - 2 * lenC,lenC,lenC)){
            print(n - 2 * lenC,lenC,lenC);
            break;
        }
        else if(check(lenC - 1,n - 2 * lenC + 1,lenC)){
            print(lenC - 1,n - 2 * lenC + 1,lenC);
            break;
        }
        else if(check(n - 2 * lenC + 1,lenC - 1,lenC)){
            print(n - 2 * lenC + 1,lenC - 1,lenC);
            break;
        }
    }
}
int main(){
    cin >> s;
    init();
    solve();
    return 0;
}                
                










