暑假第五测

Posted edsheeran

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了暑假第五测相关的知识,希望对你有一定的参考价值。

技术分享图片

技术分享图片

技术分享图片

技术分享图片

技术分享图片

技术分享图片

题解:

第一题:很明显是一个dp,但自己D不出来啊,发现前面会影响后面,后面会影响前面,不满足性质啊,当我们从前或从后都推不起走时,就可以想到补集转换了(又是它O__O"…)

t[i] 表示前i个车站所有方案,f[i]表示从一连到i的合法方案,p[i]表示连到前i个的不合法方案;

显然不合法的很好求,就是f[j]*i^(i-j) ,因为前面的只能连到j,剩下的(i-j)条随便选;f[i] = tot[i] - p[i];

技术分享图片
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const ll mod = 1e9 +7;
const int M = 5005;
ll p[M], f[M], t[M];
ll power(ll a, ll b){
    ll ret = 1;
    for(; b; b >>= 1, a = (a * a) % mod)
        if(b & 1) ret = (ret * a) % mod;
    return ret;
}

void init(int n){
    for(int i = 2; i <= n; i++) t[i] = power(i, i);
};


int main()
{

    freopen("rail.in","r",stdin);
    freopen("rail.out","w",stdout);
    int n;
    scanf("%d", &n);
      init(n);
      p[1] = 0; f[1] = t[1] = 1;
      for(int i = 2; i <= n; i++){
          ll pp = 1;
          for(int j = i-1; j >= 0; j--) pp = pp * i % mod, p[i] = (p[i] + f[j] * pp) % mod;
          f[i] = ( (t[i] - p[i]) % mod + mod) % mod;
      }
      
    printf("%I64d
", f[n]);
    return 0;
}
View Code

第二题:显然可以忽略增加的亮度只能为非负这个条件,只操作第二个,设将第二个旋转了?? 位,每个亮度增加了??,则答案为

技术分享图片

技术分享图片

这还要FFT常用的一个技巧; 就是把其中一个数组下标取反, 使 i = (n - i - 1), 那么就满足卷积的情况, 最后得到的C[i]就是x指数为i的系数;

技术分享图片
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const ll mod = 998244353;
const int M = 1000005;
int l, r, rec[M];
const double pi = acos(-1);
struct vec{
    double x, y;
    vec operator + (const vec &z) const {return (vec){x+z.x, y+z.y}; }
    vec operator - (const vec &z) const {return (vec){x-z.x, y-z.y}; }
    vec operator * (const vec &z) const {return (vec){x*z.x - y*z.y, x*z.y + y*z.x}; }
}a[M], b[M], w[M];
void fft(vec f[]){

    int nr = r, k, j; vec x, u, v;
    for(int i = 1; i < l; i++)
        if(i < rec[i]) swap(f[i], f[rec[i]]);
    for(k = 1, nr--; k < l; k <<= 1, nr--)
        for(int i = 0; i < l; i += k << 1)
            for(j = 0, x = (vec){1, 0}; j < k; j++, x = x * w[nr])
                u = f[i + j], v = x * f[i + j + k], f[i + j] = u + v, f[i + j + k] = u - v;
}

int main(){
    freopen("gift.in","r",stdin);
    freopen("gift.out","w",stdout);
    int n, m, pfa = 0, pfb = 0, zj = 0; double z = -1e8;
    scanf("%d%d", &n, &m);
    for(int i = 0; i < n; i++){
        double c; scanf("%lf", &c);
        a[i].x = c; pfa += c * c; zj += c;
    }
    for(int i = n-1; i >= 0; i--){
        double c; scanf("%lf", &c);
        b[i].x = c; pfb += c * c; zj -= c;
    }
    for(l = 1, r = 0; l < (n<<1); l <<= 1, r++);
    for(int i = 1; i <= l; i++)
        rec[i] = (rec[i>>1] >> 1) | ((i&1) << (r-1));
    w[0] = (vec){cos(2 * pi / l), sin(2 * pi / l)};
    for(int i = 1; i <= r; i++) w[i] = w[i - 1] * w[i - 1];
    fft(a); fft(b);
    for(int i = 0; i < l; i++) a[i] = a[i] * b[i];
    w[0].y = -w[0].y;
    for(int i = 1; i <= r; i++) w[i] = w[i - 1] * w[i - 1];
    fft(a);
    for(int i = 0; i < n - 1; i++)a[i + n].x += a[i].x;
    for(int i = n-1; i < 2*n - 1; i++)z = max(z, a[i].x);
    int dcz = int(floor( -zj * 1.0 / n + 0.5));
    int ans = pfa + pfb + dcz*dcz*n + 2*zj*dcz - 2*int(z / l + 0.5);
    printf("%d
",ans);

}
View Code

第三题:

技术分享图片

只有std粘了,自己没写出来

技术分享图片
#include <cstdio>
#define V_MAX 400
#define MOD 998244353
typedef void vac;
typedef bool bnt;
typedef long long lnt;
inline lnt mod(lnt x) { return x < MOD ? x : x % MOD; }
inline lnt pow(lnt a, int k)
{
    if (a < 0) return 0;
    register lnt w;
    for (w = 1; k; a = mod(a * a), k >>= 1)
        if (k & 1) w = mod(w * a);
    return w;
}
int p[V_MAX + 1], n[V_MAX + 1];
inline vac ini(int V)
{
    for (register int u = 1; u <= V; ++u) p[u] = u;
}
inline int fnd(int u)
{
    return p[u] != u ? p[u] = fnd(p[u]) : u;
}
inline vac uni(int u, int v)
{
    p[fnd(u)] = fnd(v);
}
int V, w, i, j, u, v, x, D[V_MAX + 1][V_MAX + 1];
bnt E[V_MAX + 1][V_MAX + 1];
lnt C[V_MAX + 1][V_MAX + 1], f[V_MAX + 1], ans;
int main()
{
    freopen("roof.in", "r", stdin);
    freopen("roof.out", "w", stdout);
    scanf("%d %d", &V, &w);
    ini(V);
    for (u = 1; u <= V; ++u)
        for (v = 1; v <= V; ++v)
        {
            scanf("%d", &D[u][v]);
            if (D[u][v] == 0) uni(u, v);//把边权为0的放在一个并查集里 
        }
    for (u = 1; u <= V; ++u)
        for (v = u + 1; v <= V; ++v)
            if (D[u][v] != D[v][u])
                return puts("0") == EOF;
    for (u = 1; u <= V; ++u)
        for (v = u; v <= V; ++v)
            if (fnd(u) == fnd(v) && D[u][v])
                return puts("0") == EOF;
    for (u = 1; u <= V; ++u)
        if (u == fnd(u))
            for (v = u + 1; v <= V; ++v)
                if (v == fnd(v))
                {
                    for (x = 1; x <= V && (fnd(x) == u || fnd(x) == v || D[u][v] != D[u][x] + D[x][v]); ++x);
                    E[u][v] = (x <= V);//存在dis[u][k] + dis[k][v] == dis[u][v] 
                }
    for (i = 0; i <= V; ++i)
    {
        C[i][0] = 1;
        for (j = 1; j <= i; ++j)
            C[i][j] = mod(C[i - 1][j - 1] + C[i - 1][j]);
    }
    for (i = 1; i <= V; ++i)//图的连通性 
    {
        f[i] = pow(w + 1, int(C[i][2]));
        for (j = 1; j < i; ++j)
            f[i] = mod(f[i] - mod(mod(f[j] * C[i - 1][j - 1]) * mod(pow(w + 1, int(C[i - j][2])) * pow(w, j * (i - j)))) + MOD);
    }
    for (u = 1; u <= V; ++u)//并查集大小 
        ++n[fnd(u)];
    ans = 1;
    for (u = 1; u <= V; ++u)
        if (fnd(u) == u)
            ans = mod(ans * f[n[u]]);
    for (u = 1; u <= V; ++u)
        if (fnd(u) == u)
            for (v = u + 1; v <= V; ++v)
                if (fnd(v) == v)//若有可放缩的边,就可以选择 w - D[u][v] + 1 条边使两个联通块连, 不然减去可供自由选择的方案  
                    ans = mod(ans * mod(pow(w - D[u][v] + 1, n[u] * n[v]) - (E[u][v] ? 0 : pow(w - D[u][v], n[u] * n[v])) + MOD));
    printf("%d
", int(ans));
    return 0;
}
View Code

 

 

今天的题果然是对我说再见,呵呵

 

以上是关于暑假第五测的主要内容,如果未能解决你的问题,请参考以下文章

18寒假第五测

NOI十连测 第五测 T1

NOI十连测 第五测 T2

9.26ZR七连测第五测总结

2018暑假第五周总结

2019暑假第五周总结