杭电多校2023第四场

1003

把所有的$a$排个序

然后根据贪心,一定是取连续的段

尺取法取所有可能的段即可(

#include <bits/stdc++.h>
#define pii pair<int,int>
using namespace std;
vector<pii> a;
int mp[1000005];
int T;
int main(){
    std::ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin >> T;
    while (T--){
        int K; 
        cin >> K;
        a.clear();
        for (int i = 1 ; i <= K ; i ++){
            int c;
            cin >> c;
            mp[i] = 0;
            for (int j = 1 ; j <= c ; j ++){
                int x;
                cin >> x;
                a.push_back({x,i});
            }
        }
        sort(a.begin(),a.end());
        int Len = a.size();
        int cnt = 0;
        int ans = 2e9+7;
        for (int l = 0 , r = 0; l < Len ; l ++){
            //cout << a[l].first << " " << a[l].second << endl;
            while (cnt < K && r < Len){
                pii nw = a[r];
                int x = nw.first,y = nw.second;
                mp[y] ++;
                if (mp[y] == 1) cnt ++;
                r ++; 
            }
            //cout << mp[3] << endl;
            if (cnt < K) break;    
            //cout << l << " " << r << endl;
            //cout << a[l].first << " " << cnt << " " << a[r].first << endl;
            ans = min(ans,a[r-1].first - a[l].first);
            pii nw = a[l];
            int x = nw.first,y=nw.second;
            mp[y]--;
            if (mp[y] == 0) cnt--;
        }
        cout << ans << endl;
    }
}

1004

首先根据期望的线性性,每个点是可以单独分开考虑的

也就只需要知道每个点在$k$次操作后不落在自己位置上的答案。

$f_i$表示进行了$i$次操作,某个点在自己的位置上的概率

$f_i = f_{i-1} * \frac{1+(n-1)^2}{n^2} + (1-f_{i-1}) * \frac{2}{n^2}$

前者是考虑了上一次已经在自己的位置上,所以这一次不能交换到这个位置,或者自己和自己交换(+1)

后者是考虑上一次不在自己位置上,通过一次交换换到自己位置上

然后这个东西化简一下就是$f_i = f_{i-1} * \frac{n-2}{n}+\frac{2}{n^2}$

写成矩阵形式

 

 矩阵快速幂跑一下就好了
#include <bits/stdc++.h>
#define int long long
using namespace std;
int N,M;
int T;
const int MOD = 998244353;
struct Matrix{
    int a[3][3];
    int H,W;
    Matrix operator *(const Matrix b){
        Matrix c;
        memset(c.a,0,sizeof(c.a));
        //cout << H <<" " << W <<" " << b.W << "????"<<endl;
        for (int i = 0 ; i < H; i ++)
            for (int j = 0 ; j < b.W ; j ++)
                for (int k = 0 ; k < W ; k ++){
                    (c.a[i][j] += (1ll * a[i][k] * b.a[k][j])%MOD)%=MOD;
            }
            c.H = H,c.W=b.W;
            return c;
    };
};
int Pow(int x,int y){
    int ans = 1;
    for (;y;){
        if (y & 1) ans = 1ll * ans * x %MOD;
        x = 1ll * x * x % MOD;
        y >>=1;
    }
    return ans;
}
Matrix Pow1(Matrix x,int y){
    Matrix ans;
    ans.a[0][0] = 1;ans.a[0][1] = 0;
    ans.a[1][0] = 0;ans.a[1][1] = 1;
    ans.H = 2,ans.W = 2;
    for (;y;){
        if (y & 1) ans = ans * x;
        x = x * x;
        y >>=1;
    }
    return ans;
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cin >> T;
    while (T--){
        cin >> N >> M;
        N%=MOD;
        Matrix ans;
        ans.a[0][0] = 1,ans.a[0][1] = 1;
        int inv = Pow(N,MOD-2),inv1 = Pow(N*N%MOD,MOD-2);
        ans.H = 1,ans.W = 2;
        Matrix k;
        k.a[0][0] = 1,k.a[0][1]=2ll*inv1%MOD;
        k.a[1][0] = 0,k.a[1][1]=1ll*(N-2)*inv%MOD;
        k.H=2,k.W=2;
        Matrix K1 = Pow1(k,M);
        Matrix anss = ans * K1;
        //cout << anss.a[0][1] << endl;
        long long ansss = (N - 1ll * N * anss.a[0][1]%MOD+MOD)%MOD;
        cout << ansss << endl;
    }
    return 0;
}

1006

签到,没啥好说(

注意特判一下$n==2$的case即可

其他的就大力分类一下,为1为2的概率直接算

#include <bits/stdc++.h>
using namespace std;
int main(){
    int T;
    cin >> T;
    while (T--){
        int N;
        cin >> N;
        if (N == 2){
            double a = 1,b=1;
            printf("%.9lf %.9lf\n",a,b);
            continue;
        }
        double NN =N;
        double ans = 2. - 2./NN;
        double dis = 2; 
        printf("%.9lf %.9lf\n",ans,dis);
    }
    return 0;
} 

1007

原形式不太好处理

考虑先莫比乌斯反演一下

变成$ln(n) = \sum_{d|n} f(d)$

两边$exp$一下

变成$n = \prod^{d|n} f(d)$

容易证明的是$f(p^k) = p$

打个表不难发现只有$p^k$处函数有值,其余为$1$

用Pollard-rho分解一下素因子即可。

#include "bits/stdc++.h"
using namespace std;
#define ll long long
const __int128 ONE = 1;
ll qpow(ll a,ll b,ll mod)
{
    ll res = 1;
    while(b)
    {
        if(b & 1) res = ONE * res * a % mod;
        a = ONE * a * a % mod;
        b = b >> 1;
    }
    return res;
}
int Suk[25]={0,2,3,5,7,11,13,17,19,23,29,31,37};
inline bool chk(ll n,ll a,ll b,ll x) 
{
    ll v = qpow(x , a , n);
    if (v == 1) return 1;
    int j = 1;
    while(j <= b)
    {
        if(v == n - 1) break;
        v = ONE * v * v % n;
        j ++;
    }
    if (j > b) return 0;
    return 1;
}
inline bool mr(ll n)
{
    if(n < 3 || n % 2 == 0) return n == 2;
    if(n > 37)
    {
        ll a = n - 1 , b = 0;
        while(a % 2 == 0) a >>= 1 , b ++;
        for(int i = 1 ; i <= 12 ; i ++) if(!chk(n , a ,  b , Suk[i])) return 0;
        return 1;
    }
    else
    {
        for(int i = 1 ; i <= 12 ; i ++) if(n == Suk[i]) return 1;
        return 0;
    }
}
static std::mt19937 MoBaiXHR;
inline ll F(ll x,ll c,ll MOD){return (ONE * x * x % MOD + c) % MOD;}
inline ll ABS(ll x){if(x < 0) return -x;return x;}
ll gcd(ll a,ll b)
{
    if(!b) return a;
    return gcd(b , a % b);
}
inline ll pr(ll n)
{
    if(n == 4) return 2;
    std::uniform_int_distribution<ll> Rand(3 , n - 1);
    ll x = Rand(MoBaiXHR) , y = x , c = Rand(MoBaiXHR);
    x = F(x , c , n) , y = F(F(y , c , n) , c , n);
    for(int lim = 1 ; x != y ; lim = min(lim << 1 , 128))
    {    
        ll cnt = 1;
        for(int i = 0 ; i < lim ; i ++) 
        {
            cnt = ONE * cnt * ABS(x - y) % n;
            if(!cnt) break;
            x = F(x , c , n) , y = F(F(y , c , n) , c , n);
        }
        ll d = gcd(cnt , n);
        if(d != 1) return d;
    }
    return n;
}
ll ans;
inline void MAX(ll z){if(z > ans) ans = z;}
void dfs(ll n)//非质数 
{
    ll d = pr(n);
    while(d == n) d = pr(n);
    ll d2 = n / d;
    if(mr(d)) MAX(d);
    else dfs(d);
    if(mr(d2)) MAX(d2);
    else dfs(d2);
}
ll getans(ll x)
{
    if(mr(x)) return x;
    ans = 0;
    dfs(x);
    return ans;
}
const ll MOD = 998244353;
int main()
{
    srand(time(0));
    int T;scanf("%d",&T);
    while(T --)
    {
        ll x;scanf("%lld",&x);
        if (x == 1) 
        {
            printf("1 ");
            continue; 
        }
        ll res = getans(x);
        while (x%res == 0){
            x/=res;
        }
        if (x == 1) printf("%lld ",res%MOD);
        else printf("1 ");
    }
    return 0;
}

1010

学弟打了个表,把结论猜出来了

猜完之后瞎证明了一下$(n,m)$可以规约到$(n-3,m)$或者$(n,m-3)$

然后就交了一发,然后就过了(

注意特判1*n

#include <bits/stdc++.h>
using namespace std;
int T;
int main(){
    cin >> T;
    while (T--){
        int M,N;
        cin >> M >> N;
        if (M==1 || N ==1){
            cout << (M+N)/2 << '\n';
        }
        else {
            if (M%3 ==0 || N%3 ==0) cout << 2 << '\n';
            else cout << 1 << '\n'; 
        }
    }
    return 0;
}

1011

n<=500

Floyd找最距离,并且统计一下方案数

每次循环$k$的时候,只统计最大标号为$k$的那些环,这样即可保证不重不漏。

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int MOD = 998244353;
int N,M;
int d[505][505],dis[505][505],f[505][505];
signed main(){
    std::ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    int T;
    cin >> T;
    while (T--){
        cin >> N >> M;
        memset(d,63,sizeof(d));
        memset(dis,63,sizeof(dis));
        memset(f,0,sizeof(f));
        for (int i = 1 ; i <= M ; i ++){
            int u,v,w;
            cin >> u >> v >> w;
            d[u][v] = w;
            dis[u][v] = w;
            f[u][v] = 1;
        }
        for (int i = 1 ; i <= N ; i ++)
            dis[i][i] = 0,f[i][i] = 1;
        int INF = 1e18,ans1 = 1e18,ans2 = 0;
        for (int k = 1 ; k <= N ; k ++){
            for (int i = 1 ; i < k ; i ++)
                for (int j = 1 ; j < k ; j ++){
                    if (dis[j][i] == dis[0][0] || d[i][k] ==d[0][0] || d[k][j] == d[0][0]) continue;
                    if (ans1 > dis[j][i] + d[i][k] + d[k][j]){
                        ans1 = dis[j][i] + d[i][k] + d[k][j];
                        ans2 = f[j][i]%MOD;
                    }else if (ans1 == dis[j][i] + d[i][k] + d[k][j]) (ans2 += f[j][i])%=MOD;
                }
            for (int i = 1 ; i <= N ; i ++)
                for (int j = 1 ; j <= N ; j ++){
                    if (i == k || k == j || i == j ) continue;
                    if (dis[i][k] + dis[k][j] < dis[i][j]){
                        dis[i][j] = dis[i][k] + dis[k][j];
                        f[i][j] = 0;
                    }
                    if (dis[i][k] + dis[k][j] == dis[i][j]){
                        (f[i][j] += f[i][k] * f[k][j]%MOD)%=MOD;
                    }
                }
        }
        if (ans1 == INF){
            cout << "-1 -1" <<endl;
        }else cout << ans1 << " " << ans2 << endl;
    }
    return 0;
}

1012

学弟写的,一个不知道是啥的签到题(

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>

#define x first
#define y second

using namespace std;

typedef long long LL;
typedef pair< int, int > PII;

const int N = 100010;
int n;
int qa[N], qb[N];
PII q[N];


int read()
{
    int res = 0, w = 1;
    char ch = getchar();
    while (ch != '-' && !isdigit(ch))
        ch = getchar();
    if (ch == '-')
        w = -1, ch = getchar();
    while (isdigit(ch))
        res = res * 10 + ch - '0', ch = getchar();
    return res * w;
}

void solve() {
    cin >> n;
    memset(q, 0, sizeof q);
    memset(qa, 0, sizeof qa);
    memset(qb, 0, sizeof qb);
    for(int i = 1; i <= n; i ++)
    {
        int a, b;
        cin >> a >> b;
        qa[i] = a;
        qb[i] = b;
        q[i].x = a + b;
        q[i].y = i;
        
    }

    sort(q + 1, q + n + 1);

    LL ans = 0;
    int cnt = 1;
    for(int i = n; i >= 1; i --)
    {
        int id = q[i].y;
        if(cnt % 2) ans = ans + qa[id];
        else ans = ans - qb[id];
        cnt ++;
    }

    cout << ans << endl;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int T = 1;
    cin >> T;

    while (T--)
    {
        solve();
    }

    return 0;
}

 

posted @ 2023-07-27 21:06  si_nian  阅读(77)  评论(0编辑  收藏  举报