2019中国大学生程序设计竞赛(CCPC) - 网络选拔赛

目录

[1001 ^&^]
1002 array
1003 K-th occurrence
1004 path
1005 huntian oy
1006 Shuffle Card
1007 Windows Of CCPC
1008 Fishing Master
1009 Kaguya
1010 Touma Kazusa's function
1011 sakura


1005 huntian oy

队友知道后面那串东西当a,b互质的时候就是i-j,那么变成求 \(\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{i}(i-j)[gcd(i,j)==1]\)

要求:
\(\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{i}(i-j)[gcd(i,j)==1]\)

很明显把i提前:
\(\sum\limits_{i=1}^{n}i\varphi(i)\space - \space \sum\limits_{j=1}^{i}j[gcd(i,j)==1]\)

后面那个是求:
\(\sum\limits_{i=1}^{n}i[gcd(i,n)==1]\)

显然:
\(\sum\limits_{i=1}^{n}i[gcd(i,n)==1] = \frac{n}{2}([n==1]+\varphi(n))\)

代进去得到:
\(\sum\limits_{i=1}^{n}i\varphi(i) - \frac{i}{2}([i==1]+\varphi(i))\)

即:
\(-\frac{1}{2}+\frac{1}{2}\sum\limits_{i=1}^{n}i\varphi(i)\)

这个是卷个g=id就可以得到了。

写得太豪放了差点T了,收敛一点的话还是很稳的。

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;

const int mod = 1e9 + 7;

int qpow(ll x, int n) {
    ll res = 1;
    while(n) {
        if(n & 1)
            res = res * x % mod;
        x = x * x % mod;
        n >>= 1;
    }
    return res;
}

const int inv2 = (mod + 1) >> 1;
const int inv6 = qpow(6, mod - 2);

const int MAXN = pow(1e9, 2.0 / 3.0);

int pri[MAXN + 10], pritop;
int pk[MAXN + 10];
ll sum[MAXN + 10];

void sieve(int n = MAXN) {
    sum[1] = 1;
    pk[1] = 1;
    for(int i = 2; i <= n; i++) {
        if(!pk[i]) {
            pri[++pritop] = i;
            pk[i] = i;
            sum[i] = 1ll * i * (i - 1);
            if(sum[i] >= mod)
                sum[i] %= mod;
        }
        for(int j = 1, t; j <= pritop && (t = i * pri[j]) <= n; j++) {
            if(i % pri[j]) {
                pk[t] = pk[pri[j]];
                sum[t] = sum[i] * sum[pri[j]] ;
                if(sum[t] >= mod)
                    sum[t] %= mod;
            } else {
                pk[t] = pri[j] * pk[i];
                if(t == pk[t]) {
                    sum[t] = 1ll * t * (t - t / pri[j]) ;
                    if(sum[t] >= mod)
                        sum[t] %= mod;
                } else {
                    sum[t] = sum[pk[t]] * sum[t / pk[t]] ;
                    if(sum[t] >= mod)
                        sum[t] %= mod;
                }
                break;
            }
        }
    }

    for(int i = 2; i <= n; i++) {
        sum[i] += sum[i - 1];
        if(sum[i] >= mod)
            sum[i] -= mod;
    }

}

inline int s1(int n) {
    ll t = (1ll * n * (n + 1)) >> 1;
    if(t >= mod)
        t %= mod;
    return t;
}

inline int s2(ll n) {
    ll t = n * (n + 1ll);
    if(t >= mod)
        t %= mod;
    t *= inv6;
    if(t >= mod)
        t %= mod;
    t *= (2ll * n + 1ll);
    if(t >= mod)
        t %= mod;
    return t;
}

unordered_map<int, int> Sum;

//杜教筛
inline int GetSum(int n) {
    if(n <= MAXN)
        return sum[n];
    else if(Sum.count(n))
        return Sum[n];
    //f*g=id的前缀和
    ll ret = s2(n);
    for(int l = 2, r; l <= n; l = r + 1) {
        r = n / (n / l);
        ll tmp = (s1(r) - s1(l - 1));
        if(tmp < 0)
            tmp += mod;
        tmp *= GetSum(n / l);
        if(tmp >= mod)
            tmp %= mod;
        ret -= tmp;
        if(ret < 0)
            ret += mod;
    }
    return Sum[n] = ret; // 记忆化
}

inline int Ans(int n) {
    ll tmp = GetSum(n) - 1;
    if(tmp < 0)
        tmp += mod;
    tmp *= inv2;
    if(tmp >= mod)
        tmp %= mod;
    return tmp;
}

int main() {
#ifdef Yinku
    freopen("Yinku.in", "r", stdin);
#endif // Yinku
    sieve();
    int t;
    scanf("%d", &t);
    while(t--) {
        int n, a, b;
        scanf("%d%d%d", &n, &a, &b);
        printf("%d\n", Ans(n));
    }
}

1006 Shuffle Card

一个非常搞的签到题,一开始以为要用个Treap去手写一些结构,写到Remove的时候一想不是用个set就可以了吗?

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;

set<pair<int, int> > s;
int p[100005];

int main() {
#ifdef Yinku
    freopen("Yinku.in", "r", stdin);
#endif // Yinku
    int n, m;
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; ++i) {
        int ai;
        scanf("%d", &ai);
        p[ai] = i;
        s.insert({p[ai], ai});
    }
    int cur = 0;
    for(int i = 1; i <= m; ++i) {
        int ai;
        scanf("%d", &ai);
        s.erase({p[ai], ai});
        p[ai] = cur--;
        s.insert({p[ai], ai});
    }
    for(auto si : s) {
        printf("%d ", si.second);
    }
}

猜你喜欢

转载自www.cnblogs.com/Inko/p/11402622.html