图片说明
思路:
容易发现这个题要求的就是它的所有因子之和,所以
唯一分解定理
图片说明
就可以用一个比较不错的复杂度切掉这题。
代码:

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

typedef long long int ll;
ll dcpSum(ll x){//所有因子的和(包括1)
    ll ans = 1;
    for(ll i = 2; i * i <= x; i++){
        if(x % i == 0){
            ll temp = 1;
            while(x % i == 0){
                x /= i;
                temp *= i;
            }
            ans *= (temp * i - 1) / (i - 1);//对每一个素数因子按图一公式求积。
        }
    }
    if(x > 1) ans *= (1 + x);
    return ans;
}
void solved(){
    ll n;scanf("%lld",&n);
    ll s = dcpSum(n) - n;
    /*
    ll s = 0;
    for(int i = 1; i * i <= n; i++){
        if(n % i == 0){
            s += i;
            if(i * i != n && i != 1){
                s += (n / i);
            }
        }
    }
    */
    if(s == n){
        cout << "Pure" << endl;
    }else if(s > n){
        cout << "Late" << endl;
    }else{
        cout << "Early" << endl;
    }
}
int main(){
    solved();
    return 0;
}

图片说明
思路:
模拟就行了
由于会回溯到某个位置,所以用一个数组记录每一步就行了。
代码:

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;

const int maxn = 2e5 + 10;
char s[maxn];
pair<int,int>ve[maxn];
void solved(){
    int n;scanf("%d",&n);
    scanf("%s",s + 1);
    int cur = 0;
    ve[cur] = {0,0};
    for(int i = 1; i <= n; i++){
        int x = ve[cur].first;
        int y = ve[cur].second;
        if(s[i] == 'W'){
            ve[++cur] = {x,y + 1};
        }
        if(s[i] == 'A'){
            ve[++cur] = {x - 1,y};
        }
        if(s[i] == 'S'){
            ve[++cur] = {x,y - 1};
        }
        if(s[i] == 'D'){
            ve[++cur] = {x + 1,y};
        }
        if(s[i] == 'Z'){
            cur--;
            cur = max(0,cur);
        }
    }
    cout << ve[cur].first << ' ' << ve[cur].second << endl;
}
int main(){
    solved();
    return 0;
}

图片说明
思路:
贪心:先把石头对剪刀,剪刀对布,布对石头,这样可以赢得到的分数是(min(a1,b2) + min(b1,c2) + min(c1,c2))*2
然后把用掉的全部剪掉,然后再取平局就好了。
代码:

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;

typedef long long int ll;
void solved(){
    ll a1,b1,c1,a2,b2,c2;
    ll n;cin >> n;
    cin >> a1 >> b1 >> c1;
    cin >> a2 >> b2 >> c2;
    ll t1 = min(a1,b2);
    ll t2 = min(b1,c2);
    ll t3 = min(c1,a2);
    ll s = t1 * 2 + t2 * 2 + t3 * 2;
    a1 -= t1;b2 -= t1;
    b1 -= t2;c2 -= t2;
    c1 -= t3;a2 -= t3;
    s += min(a1,a2) + min(b1,b2) + min(c1,c2);
    cout << s << endl;
}
int main(){
    solved();
    return 0;
}

图片说明
这题我题意理解错了,导致在错误的道路上越走越远,这题其实很简单。。。
我一开始看到这个题想到的是权值线段树,不过值域太大了,又离散化不了。就换其它方向,后面想,先对所有数排序,然后枚举每个数,二分出它的[l - x,r - x]的区间,然后求这个区间<=这个数在原序列的index的数量,这就转化为区间<=x数量问题了,可以考虑主席树搞。。。。最后没搞出来。。。我错就错在i<j这个条件没理解清楚。
其实这个题目就是要我们求任意两个数的和在[l,r]有多少个。
那么只需要排序,然后对每个数二分一下它的可以选的区间累和就完了。。。。害。。。一直卡在i<j上面了,其实换个题意就直接秒了。。。。
代码:

#include<iostream>
#include<algorithm>
using namespace std;

typedef long long int ll;
const int maxn = 2e5 + 10;
ll n,x,y;
ll a[maxn];
void solved(){
    cin >> n >> x >> y;
    for(int i = 1; i <= n; i++)cin >> a[i];
    sort(a + 1,a + 1 + n);
    ll ans = 0;
    for(int i = 1; i <= n; i++){
        int l = lower_bound(a + 1 + i,a + n + 1,x- a[i]) - (a);
        int r = upper_bound(a + 1 + i,a + n + 1,y - a[i]) - (a);
        ans += (r - l);
    }
    cout << ans <<endl;
}
int main(){
    solved();
    return 0;
}