2019年中国の大学対抗プログラミングコンテスト(CCPC) - トライアルネットワーク

ディレクトリ

[1001 ^&^]
1002のアレイ
1003 K番目の出現
1004パス
1005 huntianオイ
1006シャッフルカード
1007のWindows CCPCの
1008釣りマスター
1009かぐや
1010冬馬かずさの機能を
1011年桜


1005 huntianオイ

、それはその要求がなり、プライムIJ、Bの文字列の後ろのものであるとき、チームメイトが知っている\(\合計\ limits_ {I = 1} ^ {n}は\合計\ limits_ {J = 1} ^ {I}( IJ)GCD(I、J)== 1] \)

要求:
\(\和\ limits_ {i = 1} ^ {N} \和\ limits_ {J = 1} ^ {I}(IJ)GCD(i、j)は== 1] \)

もちろん、私の事前:
\(\ SUMの\のlimits_ {i = 1} ^ {N-} I \ varphi(I)\空間- \スペース\ SUM \のlimits_ {J = 1} ^ {I} J [GCD(I 、J)== 1] \)

それは求めているの背後:
\(。\ SUM \ limits_ 1 = {I}} ^ {N-I [GCD(I、N-)== 1] \)

显然:
\(\和\ limits_ {i = 1} ^ {n}はiは[GCD(I、N)== 1] = \ FRAC {n}は{2}([N == 1] + \ varphi(nは))\)

生成物を行く
(。 - [I == 1] \ SUM \ limits_ 1 = {I}} ^ {N-Iの\ varphi(I)FRAC {I \} {2}(+ \ varphi(I))\)\を

即:
\( - \ FRAC {1} {2} + \ FRAC {1} {2} \和\ 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シャッフルカード

あなたはまだセットを使用することができないと思うときに、非常にいくつかの構造Treap手書きを使用することを考えた最初の、出席の問題に従事し、削除書くでしょうか?

#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