2020 CCPC-Wannafly Winter Camp Day6

PTA
牛客

A. Convolution

题意:
给出序列\(a_{1...n}\),求\(\displaystyle \sum_{i=1}^n\sum_{j=1}^n2^{a_ia_j}\)
\(n\leq 10^5,a_i\leq 10^5\)

思路:

\[\begin{aligned} &\sum_{i=1}^n\sum_{j=1}^n2^{a_ia_j}\\ =&\sum_{i=1}^n\sum_{j=1}^n(\sqrt{2})^{2a_ia_j}\\ =&\sum_{i=1}^n\sum_{j=1}^n(\sqrt{2})^{(a_i+a_j)^2-a_i^2-a_j^2}\\ =&\sum_{k}(\sqrt{2})^{k^2}\sum_{a_i+a_j=k}(\sqrt{2})^{-a_i^2-a_j^2} \end{aligned} \]

有了这个之后,我们构造多项式\(\displaystyle f(x)=\sum_{i=0}^{n}(\sqrt{2})^{-a_i^2}x^{a_i}\)
对于第二个求和式,直接卷积计算即可。
\(2\)的二次剩余可直接暴力得到。
代码如下:

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/2/18 21:10:44
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << '\n'; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
  #define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 4e5 + 5, P = 998244353, G = 3, Gi = 332748118;
const int p = 116195171;
int n, m, r[N];
ll a[N], b[N];//注意空间要开四倍
ll qpow(ll a, ll k) {
    ll ans = 1;
    while(k) {
        if(k & 1) ans = (ans * a ) % P;
        a = (a * a) % P;
        k >>= 1;
    }
    return ans;
}
void NTT(ll *A, int type, int n) {
    for(int i = 0; i < n; i++)
        if(i < r[i]) swap(A[i], A[r[i]]);
    for(int mid = 1; mid < n; mid <<= 1) {
        ll Wn = qpow( type == 1 ? G : Gi , (P - 1) / (mid << 1)); //Wn = g ^ ((p - 1) / n)  (mod p)
        for(int j = 0; j < n; j += (mid << 1)) {
            ll w = 1;
            for(int k = 0; k < mid; k++, w = (w * Wn) % P) {
                 int x = A[j + k], y = w * A[j + k + mid] % P;
                 A[j + k] = (x + y) % P,
                 A[j + k + mid] = (x - y + P) % P;
            }
        }
    }
    if(type == -1) {
        ll inv = qpow(n, P - 2);
        for(int i = 0; i < n; i++) A[i] = A[i] * inv % P;   
    }
}
void solve(ll *a, ll *b) {
    int lim = 1, L = 0;
    while(lim <= n + m) lim <<= 1, L++;
    for(int i = 0; i < lim; i++) r[i] = (r[i >> 1] >> 1) | ((i & 1) << (L - 1));
    for(int i = n + 1; i < lim; i++) a[i] = 0;  //a,b need init
    for(int i = m + 1; i < lim; i++) b[i] = 0;
    NTT(a, 1, lim); NTT(b, 1, lim);
    for(int i = 0; i < lim; i++) a[i] = a[i] * b[i] % P;
    NTT(a, -1, lim);
}

int c[N];

void run(){
    cin >> n;
    for(int i = 1; i <= n; i++) cin >> c[i];
    for(int i = 1; i <= n; i++) {
        a[c[i]] = (a[c[i]] + qpow(qpow(p, 1ll * c[i] * c[i]), P - 2)) % P;
    }
    for(int i = 1; i <= n; i++) {
        b[c[i]] = a[c[i]];
    }
    n = m = *max_element(c + 1, c + n + 1) + 1;
    solve(a, b);
    int ans = 0;
    for(int i = 0; i <= 2 * n - 2; i++) {
        int res = 1ll * qpow(p, 1ll * i * i) * a[i] % P;
        ans = (ans + res) % P;
    }
    cout << ans << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    run();
    return 0;
}

C. 酒馆战棋

贪心即可。

Code
#include<bits/stdc++.h>
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
const int MAXN = 1e3+5,MAXM = 1e6+5,MOD = 1e9+7,INF = 0x3f3f3f3f,N=2e5;
const ll INFL = 0x3f3f3f3f3f3f3f3f;
const db eps = 1e-7;
#define lson o<<1,l,m
#define rson o<<1|1,m+1,r
#define mid l + ((r-l)>>1)
#define pii pair<int,int>
#define vii vector<pii>
#define vi vector<int>
#define x first
#define y second
using namespace std;

int T,n,A,B,C,D;
char s[MAXN];
int solve1(int a,int b,int c,int d){
    int ans=0;
    for(int i=0;i<n;i++){
        if(s[i]=='0'){
            if(c + d){
                if(d)d--,c++;
            }else if(a+b){
                if(b)b--,a++;
            }
        }else{
            if(c+d){
                if(c)c--,ans++;
                else c++,d--;
            }else if(a+b){
                if(a)a--,ans++;
                else b--,a++;
            }
        }
    }
    return ans;
}

int solve2(int a,int b,int c,int d){
    int ans=0;
   for(int i=0;i<n;i++){
        if(s[i]=='0'){
            if(c + d){
                if(!c)d--,c++;
            }else if(a+b){
                if(!a)b--,a++;
            }
        }else{
            if(c+d){
                if(!d)c--,ans++;
                else c++,d--;
            }else if(a+b){
                if(!b)a--,ans++;
                else b--,a++;
            }
        }
    }
    return ans;
}

int main(){
    ios::sync_with_stdio(false);cin.tie(0);
    cin>>T;
    while(T--){
        cin>>n>>A>>B>>C>>D;
        cin>>s;
        cout<<solve1(A,B,C,D)<<' '<<solve2(A,B,C,D)<<'\n';
    }
    return 0;
}

F. 图与三角形

容斥一下。
通过枚举角算出不合法的三角形个数,然后用总答案减去即可。
最后要除以一个\(2\),因为一个三角形不合法,就会存在两个角的两边不同色。

Code
#include<bits/stdc++.h>
using namespace std;
#define REP(i,a,b) for(int i=(a); i<(b); i++)
#define REPE(i,a,b) for(int i=(a); i<=(b); i++)
#define MAXN 5007
typedef long long ll;
typedef unsigned long long ull;
int rc[MAXN], bc[MAXN];
ull ans;
int main() {
	memset(rc,0,sizeof rc);
	memset(bc,0,sizeof bc);
	int n; scanf("%d", &n);
	int A,B,C,P,D; scanf("%d%d%d%d%d", &A, &B, &C, &P, &D);
	REPE(i,1,n) REPE(j,i+1,n) {
		if(((ll)A*(i+j)*(i+j)+(ll)B*(i-j)*(i-j)+C)%P>D) {
			bc[i]++, bc[j]++;
		} else {
			rc[i]++, rc[j]++;
		}
	}
	ans=0;
	REPE(i,1,n) {
		ans+=bc[i]*rc[i];
	}
	ans/=2;
	ans = (ull)n*(n-1)*(n-2)/6-ans;
	printf("%llu\n", ans);
}

G. 单调栈

显然若\(f(1)\)一定为\(1\),对于所有\(f\)值相同的位置,我们依次从小到大倒序来放置即可。
然后将所有的\(f\)值减一,再重复执行以上操作即可。
贪心的正确性:

  • \(f(1)=1\)显然,然后对于所有为\(1\)的位置,若存在\(i,j,i<j\),有\(a_i<a_j\),那么必然\(f_i<f_j\),所以必然是倒序。因为要求字典序最小,所以依次放置。

  • 对于多个\(f=-1\),因为字典序最小,我们能不处理则不处理,否则会使前面的增大。

代码如下:

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/2/17 20:53:27
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << '\n'; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
  #define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 100 + 5;

int n;
int f[N], ans[N];
bool chk[N];

void run(){
    memset(chk, 0, sizeof(chk));
    int Min = 1;
    cin >> n;
    for(int i = 1; i <= n; i++) cin >> f[i];
    while(1) {
        int fir = -1;
        for(int i = 1; i <= n; i++) {
            if(!chk[i]) {
                if(f[i] == -1) f[i] = 1;
                fir = i; break;
            }
        }
        if(fir == -1) break;
        for(int i = n; i >= 1; i--) if(!chk[i]) {
            if(f[i] == 1) {
                chk[i] = true;
                ans[i] = Min++;
            } else if(f[i] > 1) {
                f[i] -= 1; 
            }
        }
    }
    for(int i = 1; i <= n; i++) cout << ans[i] << " \n"[i == n];
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    int T; cin >> T;
    while(T--) run();
    return 0;
}

H. 异或询问

题意:
给出一个序列\(a_{1...n}\),定义\(f(x)\)为有几个\(a_i\)小于等于\(x\)
现有\(q\)个询问,每次给定\(l,r,x\),需要求\(\displaystyle\sum_{i=l}^rf^2(i\ xor\ x)\)

思路:

  • 显然可以将询问拆为两个前缀相减,那么现在只需要考虑求\(\sum_{i=0}^rf^2(i\ xor\ x)\)
  • 因为\(i\)的变化为\(0\rightarrow r\),我们可以类似于数位\(dp\)那样来考虑:假设当前\(r\)最高位为\(w\),也就是说\(bit(r,w)=1\),那么这位取\(0\)的话,后面可以任意取,所以\(i\ xor\ r\)此时为连续的一段区间;如果这一位取\(1\),那么就枚举下一位再类似考虑就行。
  • 也就是说我们按二进制位从高到低考虑,将\(i\ xor\ x,0\leq i\leq r\)可以拆分为若干个连续的区间,接下来考虑的就是怎么求\(\sum_{i=l}^rf(i)\)
  • 这个就很好求了,直接预处理后二分即可。

细节见代码:

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/2/19 11:47:00
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << '\n'; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
  #define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5, MOD = 998244353;

int n, q;
int a[N];
vector <pii> b;
ll pre[N], w[N];

int sum(int x) {
    int p = upper_bound(all(b), MP(x, INF)) - b.begin() - 1;
    if(p < 0) return 0;
    return ((p > 0 ? pre[p - 1] : 0) + 1ll * (x - b[p].fi + 1) * w[p] % MOD) % MOD;
}

int solve(int n, int x) {
    int res = 0;
    for(int i = 29; i >= 0; i--) {
        if(n >> i & 1) {
            int t = (n ^ x) >> i << i;
            int st = t ^ (1 << i);
            int ed = st + (1 << i) - 1;
            res = (1ll * res + sum(ed) - sum(st - 1) + MOD) % MOD;
        }
    }
    int t = n ^ x;
    res = (1ll * res + sum(t) - sum(t - 1) + MOD) % MOD;
    return res;
}

void run() {
    for(int i = 1; i <= n; i++) cin >> a[i];
    sort(a + 1, a + n + 1);
    for(int i = 1, j; i <= n; i = j + 1) {
        j = i;
        while(j < n && a[j + 1] == a[j]) ++j;
        b.push_back(MP(a[i], j - i + 1));
    }
    for(int i = 0; i < sz(b); i++) {
        if(i == 0) w[i] = b[i].se;
        else w[i] = w[i - 1] + b[i].se;
    }
    for(int i = 0; i < sz(b); i++) {
        w[i] = 1ll * w[i] * w[i] % MOD;   
    }
    for(int i = 0; i < sz(b); i++) {
        if(i + 1 < sz(b)) {
            if(i == 0) pre[i] = 1ll * (b[i + 1].fi - b[i].fi) * w[i] % MOD;
            else pre[i] = (pre[i - 1] + 1ll * (b[i + 1].fi - b[i].fi) * w[i] % MOD) % MOD;
        }
    }
    while(q--) {
        int l, r, x; cin >> l >> r >> x;
        int ans = (solve(r, x) - solve(l - 1, x) + MOD) % MOD;   
        cout << ans << '\n';
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    while(cin >> n >> q) run();
    return 0;
}

I. 变大!

题意:
给出一个序列\(a[1...n]\),每次可以选择一个\(i(2\leq i<n)\),然后将\(a[i-1],a[i],a[i+1]\)都变为\(max(a[i-1],a[i],a[i+1])\)
现在进行\(k\)次这样的操作,目标是最大化\(\sum_{i=1}^n a_i\)
现在对于\(k=1...n\)依次输出最终答案。
\(n\leq 100\)

思路:
显然最后的答案都是一段一段的形式,每一段的值都为该段最大值。
然后还有一个性质:

  • 对于长度为\(l\)的一段区间,需要将其全变为最大值的操作次数为\(\lfloor\frac{l}{2}\rfloor\)

那么我们枚举每个数,再枚举其分段,然后做个简单\(dp\)就行了。
时间复杂度\(O(n^3)\)

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/2/17 21:24:13
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << '\n'; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
  #define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 50 + 5, M = 20 + 5;

int n;
int a[N];
int dp[N][N];

void run(){
    memset(dp, 0, sizeof(dp));
    cin >> n;
    for(int i = 1; i <= n; i++) cin >> a[i];
    for(int i = 1; i <= n; i++) {
        int mx = a[i];
        for(int j = i; j >= 1; j--) {
            mx = max(mx, a[j]);
            int c = (i - j + 1) / 2;
            for(int k = c; k <= n; k++) {
                dp[i][k] = max(dp[i][k], dp[j - 1][k - c] + (i - j + 1) * mx);   
            }
        }
    }
    for(int i = 1; i <= n; i++) cout << dp[n][i] << " \n"[i == n];
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    int T; cin >> T;
    while(T--) run();
    return 0;
}

J. K重排列

题意:
对于一个排列\(p[1\cdots n]\),设\(p^k[i]=p[p^{k-1}[i]]\),且\(p^1[i]=p[i]\)
如果存在一个\(k\),使得对于所有的\(i\)都有\(p^k[i]=i\),那么\(k\)\(p\)的一个周期。
最后统计满足\(k\)为其一个周期的排列个数。

思路:
题解已经说的很清楚了,在比赛的时候考虑的是将\(n\)个点划分为若干个循环,每个循环的长度整除\(k\)
然后想的是直接搜索,感觉问题应该不大...
直接附上题解说的吧。

给出暴力的代码:

Code
#include<bits/stdc++.h>
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
const int MAXN = 50+5,MAXM = 1e6+5,MOD = 998244353,INF = 0x3f3f3f3f,N=2e5;
const ll INFL = 0x3f3f3f3f3f3f3f3f;
const db eps = 1e-7;
#define lson o<<1,l,m
#define rson o<<1|1,m+1,r
#define mid l + ((r-l)>>1)
#define pii pair<int,int>
#define vii vector<pii>
#define vi vector<int>
#define x first
#define y second
using namespace std;
int n,T;
ll ans=0,K,fact[MAXN],inv[MAXN];

ll qpow(ll a,ll b){
    ll ans=1;
    for(;b;b>>=1,a=a*a%MOD)if(b&1)ans=ans*a%MOD;
    return ans;
}
ll C(int a,int b){
    if(a<b)return 0;
    if(a==b || b==0)return 1;
    return fact[a] * inv[a-b]%MOD*inv[b]%MOD;
}
void dfs(int sum,int pre,ll res,int cnt){
    if(!sum){
        res = res * inv[cnt]%MOD;
        ans = (ans + res)%MOD;
        //cout<<cnt<<' '<<res<<'\n';
        return ;
    }
    for(int i=pre;i<=sum;i++){
        if(K%i==0){
            //cout<<sum<<' '<<i<<' '<<C(sum,i)<<'\n';
            ll tmp = res * C(sum,i)%MOD*fact[i-1]%MOD;
            if(i != pre){
                tmp = tmp * inv[cnt] % MOD;
                dfs(sum-i,i,tmp,1);
            }else dfs(sum-i,i,tmp,cnt+1);
        }
    }
}
int main(){
    ios::sync_with_stdio(false);cin.tie(0);
    fact[1] = fact[0] = 1;
    for(int i=2;i<=50;i++)fact[i] = fact[i-1]*i%MOD;
    inv[50] = qpow(fact[50],MOD-2);
    for(int i=49;i>0;i--)inv[i] = inv[i+1]*(i+1)%MOD;
    inv[0]=1;
    cin>>T;
    while(T--){
        cin>>n>>K;
        ans = 0;
        dfs(n,1,1,0);
        cout<<ans<<'\n';
    }
    return 0;
}

K. 最大权值排列

接下来签到四连。

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/1/17 13:32:46
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << '\n'; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
  #define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5;

int n;

void run(){ 
    int now = 1;
    for(int i = 1; i <= n; i++) {
        cout << now << ' ';
        if(i <= (n - 1) / 2) now += 2;   
        else {
            if(now & 1) {
                if(n & 1) --now;
                else ++now;
            }
            else now -= 2;
        }
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    while(cin >> n) run();
    return 0;
}

L. 你吓到我的马了.jpg

BFS。

Code
#include<bits/stdc++.h>
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
const int MAXN = 1e2+5,MAXM = 1e6+5,MOD = 1e9+7,INF = 0x3f3f3f3f,N=2e5;
const ll INFL = 0x3f3f3f3f3f3f3f3f;
const db eps = 1e-7;
#define lson o<<1,l,m
#define rson o<<1|1,m+1,r
#define mid l + ((r-l)>>1)
#define pii pair<int,int>
#define vii vector<pii>
#define vi vector<int>
#define x first
#define y second
using namespace std;

int n,m;
int dx[8] = {-2,-2,2,2,-1,1,-1,1};
int dy[8] = {-1,1,-1,1,-2,-2,2,2};
int dx2[8] = {-1,-1,1,1,0,0,0,0};
int dy2[8] = {0,0,0,0,-1,-1,1,1};
char mp[MAXN][MAXN];
int vis[MAXN][MAXN];
inline bool bound(int x,int y){
    return x>=1&&x<=n&&y>=1&&y<=m;
}
int main(){
    ios::sync_with_stdio(false);cin.tie(0);
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        cin>>(mp[i]+1);
    }
    int sx,sy;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(mp[i][j]=='M'){
                sx = i,sy=j;
            }
        }
    }
    queue<pii> q;
    q.push({sx,sy});
    vis[sx][sy] = 1;
    pii nw;
    //cout<<sx<<' '<<sy<<'\n';
    while(!q.empty()){
        pii a = q.front();q.pop();
        for(int i=0;i<8;i++){
            nw.x = a.x + dx[i];
            nw.y = a.y + dy[i];
            if(bound(nw.x,nw.y) && mp[a.x+dx2[i]][a.y+dy2[i]]!='X' && mp[nw.x][nw.y] != 'X' && !vis[nw.x][nw.y]){
                q.push(nw);
                vis[nw.x][nw.y] = vis[a.x][a.y] + 1;
                //cout<<nw.x<<' '<<nw.y<<' '<<vis[nw.x][nw.y]<<'\n';
            }
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(vis[i][j])cout<<vis[i][j]-1<<" \n"[j==m];
            else cout<<"-1"<<" \n"[j==m];
        }
    }
    return 0;
}

M. 自闭

模拟。

Code
#include<bits/stdc++.h>
using namespace std;
#define REP(i,a,b) for(int i=(a); i<(b); i++)
#define G0(x) memset(x,0,sizeof(x))
#define MAXN 107
bool sub[MAXN];
bool ac[MAXN][17];
int acc[MAXN];
int was[MAXN][17];
int wac[MAXN][17];
int accnt[17];
int zb[MAXN];
int n,m,W;
int main() {
	scanf("%d%d%d", &n, &m, &W);
	G0(sub),G0(ac),G0(was),G0(wac),G0(accnt),G0(zb),G0(acc);
	REP(i,0,W) {
		int x,y,c; scanf("%d%d%d", &x, &y, &c); x--,y--;
		sub[x]=1;
		if(c) {
			if(!ac[x][y]) accnt[y]++,ac[x][y]=1,acc[x]++;
			wac[x][y]=0;
		} else {
			wac[x][y]++;
			was[x][y]=max(was[x][y],wac[x][y]);
		}
	}
	REP(i,0,n) {
		if(!sub[i]) {
			zb[i]=998244353;
			continue;
		} else if(!acc[i]) {
			zb[i]=1000000;
			continue;
		} else if(acc[i]==m) {
			zb[i]=0;
			continue;
		}
		REP(j,0,m) {
			if(!ac[i][j] && accnt[j]>0) {
				zb[i]+=20;
			}
			if(!ac[i][j] && accnt[j]>=n/2) {
				zb[i]+=10;
			}
			zb[i]+=was[i][j]*was[i][j]*((!ac[i][j])+1);
		}
	}
	REP(i,0,n) {
		printf("%d\n", zb[i]);
	}
	
}

N. 合并!

稍微手模一下就可以发现怎么合并答案都是一样。

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/1/17 13:05:18
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << '\n'; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
  #define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 2000 + 5;

int n;
int a[N];

void run(){
    for(int i = 1; i <= n; i++) cin >> a[i];
    ll ans = 0;
    for(int i = 1; i <= n; i++) {
        for(int j = i + 1; j <= n; j++) {
            ans += a[i] * a[j];
        }
    }
    cout << ans << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    while(cin >> n) run();
    return 0;
}
posted @ 2020-02-17 20:10  heyuhhh  阅读(443)  评论(0编辑  收藏  举报