2022 SDNU-ACM training competition solution

First of all, I would like to thank all the testers for their careful preparation, the testers for their hard work, and the contestants for their active participation

answer

Problem A The Return of Liu Yuxin【Mathematics】

Issuer: bhq

Unexpectedly, the first blood was taken away by wyx, who played in the training match after beating Shanda's cattle game!

Title description:

计算 ( ∑ 0 < d < p d − 1 ) m (\sum_{0<d<p}d^{-1})^m (0<d<pd1)m , whered − 1 d^{-1}d1 isddd in moduloppp ( p p p is a prime number) in the sense of the multiplicative inverse element, since the result may be very large, please correct998244353 9982443539 9 8 2 4 4 3 5 3 model.

Ideas:

This question is a small thinking question, for a prime number ppFor p ,ppThe inverse of each element of the residual system of p still constitutes its residual system. we rememberppThe remainder of p is PPP , fora ∈ P a \in PaFor P ,aaThere are two cases for the inverse of a . The first case isa − 1 = aa^{-1}=aa1=a , the second case isa − 1 = b , b ∈ P a^{-1}=b,b\in Pa1=b,bP , thenb − 1 = ab^{-1}=ab1=a , so in general, the inversion will not change anything, and the brackets are essentially the sum of an arithmetic sequence. Note the data range,ppp will be large, sop ∗ ( p − 1 ) p*(p-1)p(p1 ) will explodelong long long longl o n g l o n g , so first take the modulo998244353 9982443539 9 8 2 4 4 3 5 3 , divided by2 22 converts to multiply by2 2The inverse of 2 , and then do a quick exponentiation.

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
#define ll long long
const ll N = 1e5+5;
const ll mod = 998244353;

ll qpow(ll a, ll b)
{
    
    
    a %= mod;
    ll ans = 1;
    while(b)
    {
    
    
        if(b & 1)
            ans = (ans * a) % mod;
        a = (a * a) % mod;
        b >>= 1;
    }
    return ans;
}

int main()
{
    
    
    std::ios::sync_with_stdio(false);
    ll p, m;
    cin >> p >> m;
    p %= mod;
    ll ans = (p * (p-1) % mod) * qpow(2, mod-2) % mod;
    cout << qpow(ans, m) << '\n';
	return 0;
}

Problem B, take it easy and find an electronics factory to work [interval greed/difference constraints]

Issuer: LYJ

It's a pity that no one has passed this question during the competition

Title description:

Given m kinds of conditions (l[i],r[i],c[i]), it is required to construct a string of 01 so that l[i]there r[i]is at least c[i]one 1 in it. What is the string with the least number of 1s that satisfies all the conditions?

Idea 1

The classic interval greedy problem, we sort the m conditions in rdescending order

For an interval [l,r], we first calculate how many of them already exist in the interval 1, and select the closest rones that are not 1 for the remaining 1.

So we need a data structure to maintain the number of interval query/update 1, and also need a data structure to know the position that is not 1 ahead of the current position to update

We can use a tree array or a line segment tree for interval maintenance

Use union search to maintain ithe first position that is not 1

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

#define endl '\n'
#define inf 0x3f3f3f3f
#define mod 998244353
#define No cout<<"No\n"
#define Yes cout<<"Yes\n"
#define m_p(a,b) make_pair(a, b)
#define mem(a,b) memset((a),(b),sizeof(a))
#define lowbit(x) (x&(-x))
#define io ios::sync_with_stdio(false)
typedef long long ll;
typedef pair <int,int> pii;

#define MAX 300000 + 50
int n, m, k, x, y, p;
struct ran{
    
    
    int l, r, x;
    int id;
    bool operator < (const ran &a)const{
    
    
        return r < a.r;
    }
}tr[MAX];

int ans[MAX];
int fa[MAX];
int getfa(int x){
    
    
    return x == fa[x] ? x : fa[x] = getfa(fa[x]);
}

int ar[MAX];
void add(int id){
    
    
    while(id <= n){
    
    
        ++ar[id];
        id += lowbit(id);
    }
}
int getans(int id){
    
    
    int ans = 0;
    while(id){
    
    
        ans += ar[id];
        id -= lowbit(id);
    }
    return ans;
}

void work(){
    
    
    cin >> n >> m;
    for(int i = 1; i <= m; ++i){
    
    
        cin >> tr[i].l >> tr[i].r >> tr[i].x;
        tr[i].id = i;
    }
    sort(tr+1, tr+1+m);
    for(int i = 1; i <= n; ++i)fa[i] = i;
    for(int i = 1; i <= m; ++i){
    
    
        tr[i].x -= (getans(tr[i].r) - getans(tr[i].l - 1));
        if(tr[i].x <= 0)continue;
        for(int id = getfa(tr[i].r); tr[i].x;id = getfa(id)){
    
    
            add(id);
            --tr[i].x;
            fa[id] = getfa(id-1);
            ans[id] = 1;
        }
    }
    for(int i = 1; i <= n; ++i)cout << ans[i] << " \n"[i==n];
}


int main(){
    
    
    io;
    work();
    return 0;
}

Idea 2:

Differential constraint board sub-question

Suppose the desired array is calledar[i]

Then we make sum[i]the prefix and array representing the ar array, for which l, r, cwe can convert to sum[r]-sum[l-1] >= c, because we are looking for the minimum value, so run the longest path, use >the number, that is sum[r] >= sum[l-1] + c, build a side l-1with rthe weight of c, but in order to avoid Using 0, we change lto r+1build an edge

Because it is a prefix sum, and there is at most one 1 in one position, 0≤sum[i]-sum[i-1]≤1the condition for establishing one, when disassembled, is sum[i]≥sum[i-1]+0to build an edge with a weight of 0 from i-1to to , and to create an edge with a weight of -1 from to to , Because there are negative weight edges, run SPFAisum[i-1]≥sum[i]-1ii-1

The obtained prefix and the array are then differentiated to obtain the original array

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

#define endl '\n'
#define inf 0x3f3f3f3f
#define mod 998244353
#define No cout<<"No\n"
#define Yes cout<<"Yes\n"
#define m_p(a,b) make_pair(a, b)
#define mem(a,b) memset((a),(b),sizeof(a))
#define io ios::sync_with_stdio(false)
typedef long long ll;
typedef pair <int,int> pii;

#define MAX 1000000 + 50
int n, m, k, l, r, c, p;

int tot;
int head[MAX];
struct ran{
    
    
    int to, nex, val;
}tr[MAX];
inline void add(int u, int v, int c){
    
    
    tr[++tot].to = v;
    tr[tot].val = c;
    tr[tot].nex = head[u];
    head[u] = tot;
}

int dis[MAX];
bool vis[MAX];
void spfa(){
    
    
    deque<int>q;
    for(int i = 1; i <= n; ++i){
    
    
        q.push_back(i);
        dis[i] = 0;
        vis[i] = 1;
    }
    while (!q.empty()) {
    
    
        int u = q.front();q.pop_front();vis[u] = 0;
        for(int i = head[u]; i; i = tr[i].nex){
    
    
            int v = tr[i].to;
            if(dis[v] < dis[u] + tr[i].val){
    
    
                dis[v] = dis[u] + tr[i].val;
                if(!vis[v]){
    
    
                    vis[v] = 1;
                    if(!q.empty() && dis[q.front()] > dis[v])q.push_front(v);
                    else q.push_back(v);
                }
            }
        }
    }
    for(int i = 2; i <= n + 1; ++i){
    
    
        cout << dis[i] - dis[i - 1] << " \n"[i==n+1];
    }
}


void work(){
    
    
    cin >> n >> m;
    for(int i = 1; i <= n; ++i){
    
    
        add(i, i+1, 0);
        add(i+1, i, -1);
    }
    for(int i = 1; i <= m; ++i){
    
    
        cin >> l >> r >> c;
        add(l, r+1, c);
    }
    spfa();
}


int main(){
    
    
    io;
    work();
    return 0;
}

Problem C I have no brain [play table/matrix fast power]

Issuer: JBQ

It's a pity that no one has done a question like this

Title description:

Rabbits are born, the number of rabbits is the Fibonacci sequence

Ask how many rabbits were born from the l100 millionth year to the r100 millionth year, and the rabbits born do not include the lrabbits born in the 1st year, and no rabbits were born in the 0th year

Ideas:

If you look at the data range, you will find that 0<=l,r<=300it is obviously a simple table problem. We can run Fibonacci violently to find the Fibonacci number from 0 billion to 30 billion. When running, we can use three variables to switch back and forth. To avoid the problem that the array cannot be opened, the table can be printed out after a few minutes of running locally, and then ithe Fibonacci number of the billionth year is recorded in the array. This is a prefix sum. Use the nature of the prefix sum to calculate which interval to query. OK

Because it involves subtraction, there will be negative numbers, remember to +mod and then take the mod

Of course, this is a board question about fast exponentiation of matrices, and you can pass it if you set it.

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const double pi = acos(-1);
const ll mod = 998244353;

ll qz[] = {
    
    0,174079809,350529837,540135893,248983311,188662298,163535581,26424980,29356346,377822061,990450892,302998835,770343747,552350183,15396855,424926956,88941576,763450547,898383525,17528340,412076452,206977951,379701090,699742036,380345178,630855901,215773428,670848941,708850059,759042535,370671059,914173509,546356307,5232597,694566734,700347768,106284179,48542533,336670082,271726108,760855650,177724054,224473711,884667489,399724153,120220241,856574745,909795978,378135714,190545578,146687109,355925757,346733017,121393103,736658703,436961107,259288615,749208626,766089397,194102954,638000257,519167820,655288960,872163139,532492585,496860676,774844232,39275773,498133671,371136296,389528837,693448612,466324418,925981560,611164646,232564044,13688323,711293940,965100438,399071469,90757559,803023736,326830157,805286509,254912924,102214332,274197678,524443975,289792461,926311141,67790802,467964271,333938384,258436673,71452804,683937426,404752872,198446430,838706053,501212411,167522484,427792454,240181277,502955299,959889585,956146057,947694331,472908698,164907180,295903902,789545095,819397095,885110015,187068234,859373205,461949265,833268322,188830126,620580489,81476315,799979868,872780884,639335743,214604713,725457919,602768712,404752628,261042264,452466864,264650298,83342962,525806466,242898501,648090615,211023083,216855464,271913720,956861944,389777898,246477234,277948122,261757157,583255005,168253729,301612668,617239094,32212131,382009316,914610194,865430047,367903763,582568911,237402789,907511216,795851825,535685886,184939689,215710754,830040275,404086346,178845145,133296369,768509020,34346825,579080786,789976801,291262952,445117166,638901953,466760442,524216211,990440339,351571978,434005891,41322877,67726455,857058332,886192362,908954613,601948714,350088780,970979040,656331119,804659347,151691585,686880448,555777756,212851886,562313640,685580955,792479573,305192341,212979909,755367688,422525487,279142234,908459752,116009277,138047368,74170783,908569483,278453199,832057846,480474473,744340566,524823005,490844667,491530577,908970624,578875419,778732446,981441931,930496121,455524732,336924607,337585594,22617186,337729446,273285818,118523424,123031060,470173959,2335851,265337201,239746786,649284192,963473000,267280391,367303681,768114245,941758551,454661791,605958520,201446298,646412496,455731820,428662317,558589444,262367234,641423282,726013475,897721843,206526423,904882765,25830392,995523912,304380590,881069167,922277936,949431046,116187873,599781594,404612175,340924556,688094980,354391975,701905403,220003631,506648913,905201506,848118900,691020931,611886852,46282188,735419146,223099686,554098962,124828843,283063450,176654870,404630446,796542941,770962213,676150050,456492707,909163219,971214787,400826726,254478508,463527309,686895321,688734626,781497186,460395419,411403102,778541634,894602464,915995672,604742042,160537389,89030071,956235246,605154828,169835294,549232325,789998297,189968249,55896911,957522027,790730960,238229067};

int main()
{
    
    
	ll T,p,q;
	cin>>T;
	while(T--){
    
    
		cin>>p>>q;
		cout<<(qz[q] - qz[p] + mod)%mod<<endl;
	}
	return 0;
}
#include <bits/stdc++.h>
using namespace std;

#define endl '\n'
#define inf 0x3f3f3f3f
#define mod7 998244353
#define mod9 998244353
#define m_p(a,b) make_pair(a, b)
#define mem(a,b) memset((a),(b),sizeof(a))
#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
typedef long long ll;
typedef pair <int,int> pii;

#define MAX 300000 + 50
int n, m, k, x, y;
int tr[MAX];

struct Matrix{
    
    
    ll tr[2][2];
    Matrix(){
    
    
        mem(tr, 0);
    }
    Matrix operator * (const Matrix y){
    
    
        Matrix ans;
        for(int i = 0; i < 2; ++i){
    
    
            for(int j = 0; j < 2; ++j){
    
    
                for(int k = 0; k < 2; ++k){
    
    
                    (ans.tr[i][j] += tr[i][k] * y.tr[k][j]) %= mod7;
                }
            }
        }
        return ans;
    }
    void operator = (const Matrix b){
    
    
        for(int i = 0; i < 2; ++i){
    
    
            for(int j = 0; j < 2; ++j){
    
    
                tr[i][j] = b.tr[i][j];
            }
        }
    }
};
ll getans(ll n){
    
    
    Matrix ans, cnt;
    ans.tr[0][0] = ans.tr[1][1] = 1;
    cnt.tr[0][0] = cnt.tr[0][1] = cnt.tr[1][0] = 1;
    while(n){
    
    
        if(n & 1)ans = ans * cnt;
        cnt = cnt * cnt;
        n /= 2;
    }
    return ans.tr[0][0];
}

ll fuck[MAX];

void work(){
    
    
    for(ll i = 1; i <= 300; ++i){
    
    
        fuck[i] = getans(i * 100000000ll - 1);
    }
    int t;cin>>t;
    while(t--){
    
    
        cin >> x >> y;
        cout << (fuck[y] - fuck[x] + mod7) % mod7 << endl;
    }
}


int main(){
    
    
    io;
    work();
    return 0;
}

Problem D I am pig feed, I wish you a happy day [sign in]

Issuer: LYJ

I didn't think of the hello world question at first, but suddenly I was notified that the sophomore would not be able to do it. This set of questions was only for the freshman, so I added one overnight

If there is no such question, everyone is likely to sit in prison for five hours

I still want to wish Sister Snake a happy birthday!

Title description:

Just output "Happy Birthday Sister Snake!!!"

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

#define endl '\n'
#define inf 0x3f3f3f3f
#define mod7 1000000007
#define mod9 998244353
#define m_p(a,b) make_pair(a, b)
#define mem(a,b) memset((a),(b),sizeof(a))
#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
typedef long long ll;
typedef pair <int,int> pii;

#define MAX 300000 + 50
int n, m, k, x;
int tr[MAX];

void work(){
    
    
    cout << "蛇姐生日快乐!!!";
}

int main(){
    
    
    io;
    work();
    return 0;
}

Problem E has no special meaning, I just want to mix up the longest topic name, and then let everyone click in to do this problem

Issuer: NXY

Regarding the fact that xygg produced a weight line segment tree but was randomly stuck by two people with other ideas

Ideas:

The first method: discretization + weight line segment tree
We found that each number itself is useless, all we need is the size relationship between them, and NNN is not very large, so discretization is considered.
Then the discretized sequence is maintained with a weight line segment tree.

The second approach: balanced tree
dynamic query kkK large number, it is easy to think of the balance tree to maintain directly

The third approach: to the top heap
szz \texttt{szz}szz 's practice in the examination room.

The fourth approach: chairman tree
gts \texttt{gts}gts examination practice

If you want to make up questions, it is recommended to learn the first method and the third method. The first method is very typical and common, and it is an indispensable skill point. The third method is very clever and interesting in thinking, and the code is short and easy to understand. It is also recommended that everyone learn

#include<bits/stdc++.h>

using namespace std;
const int N = 1e5 + 10;

int n,w;
int a[N],b[N],c[N];

bool cmp(int x , int y)
{
    
    return x > y;}

struct NO
{
    
    
    int l;
    int r;
    int w;
};

struct SigmentT
{
    
    
    NO t[N * 4];
    void Build(int p , int l , int r)
    {
    
    
        t[p].l = l; t[p].r = r;
        if(l == r) return;
        int mid = (l + r) >> 1;
        Build(p << 1 , l , mid);
        Build(p << 1 | 1 , mid + 1 , r);
    }

    void Updata(int p , int w)
    {
    
    
        if(t[p].l == t[p].r) {
    
    
            t[p].w++; return;
        }
        int mid = (t[p].l + t[p].r) >> 1;
        if(w <= mid) Updata(p << 1 , w);
        else Updata(p << 1 | 1 , w);
        t[p].w = t[p << 1].w + t[p << 1 | 1].w;
    }

    int Query(int p , int k)
    {
    
    
        if(t[p].l == t[p].r) return t[p].l;
        if(t[p << 1].w < k) return Query(p << 1 | 1, k - t[p << 1].w);
        else return Query(p << 1 , k);
    }
}tr;

int main()
{
    
    
    //freopen("aa.in","r",stdin);
    scanf("%d%d",&n,&w); 
    for(int i = 1; i <= n; i++)
        scanf("%d",&a[i]) , b[i] = a[i];

    std::sort(b + 1 , b + 1 + n);
    int LEN = std::unique(b + 1 , b + 1 + n) - b - 1;
    for(int i = 1, tmp; i <= n; i++)
        tmp = a[i] , a[i] = std::lower_bound(b + 1 , b + 1 + LEN , a[i]) - b , c[a[i]] = tmp;
    
    tr.Build(1 , 0 , LEN);
    for(int i = 1; i <= n; i++)
    {
    
    
        int m = max(1 , i * w / 100);
        tr.Updata(1 , a[i]);
        printf("%d ",c[tr.Query(1 , i - m + 1)]);
    }
    
}
#include<bits/stdc++.h>

const int N = 3e5 + 10;

int n,w;
int a[N];

struct No {
    
    
    int p,siz,val,sel,son[2];
};

struct SBT{
    
    
    int rt,idx;
    No t[N];

    void Pushup(int u) {
    
    
        t[u].siz = t[t[u].son[0]].siz + t[t[u].son[1]].siz + t[u].sel;
    }

    void rotate(int u) {
    
    
        int y = t[u].p , z = t[y].p;
        int k = t[y].son[1] == u;
        t[z].son[t[z].son[1] == y] = u , t[u].p = z;
        t[y].son[k] = t[u].son[k ^ 1] , t[t[u].son[k ^ 1]].p = y;
        t[u].son[k ^ 1] = y , t[y].p = u;
        Pushup(y) , Pushup(u);
    }

    void Splay(int u , int p) {
    
    
        while(t[u].p != p) {
    
    
            int y = t[u].p , z = t[y].p;
            if(z != p)
                if((t[z].son[1] == y) ^ (t[y].son[1] == u))
                    rotate(u);
                else rotate(y);
            rotate(u);
        }
        if(!p) rt = u;
    }

    void insert(int val) {
    
    
        int u = rt , p = 0;
        while(u) {
    
    
            if(val == t[u].val) break;
            p = u , u = t[u].son[val > t[u].val];
        }
        if(!u) u = ++idx;
        t[u].sel++;t[u].p = p;t[u].val = val;
        if(p) t[p].son[val > t[p].val] = u;
        Splay(u , 0);
    }

    int getk(int k) {
    
    
        int u = rt;
        while(1) {
    
    
            if(k <= t[t[u].son[0]].siz) u = t[u].son[0];
            else if(k <= t[t[u].son[0]].siz + t[u].sel) {
    
    
                Splay(u , 0); return t[u].val;
            }
            else k -= t[t[u].son[0]].siz + t[u].sel , u = t[u].son[1];
        }
    }
}tr;

const int inf = 1e9;

int main() {
    
    
    //freopen("aa.in","r",stdin);
    scanf("%d%d",&n,&w); tr.insert(-1) , tr.insert(inf);
    for(int i = 1 , x; i <= n; i++) {
    
    
        scanf("%d",&x); tr.insert(x);
        int end = std::max(1 , i * w / 100);
        printf("%d ",tr.getk(i - end + 1 + 1));
    }
}

Problem F Taki 1000 (hard version)【Structure】

Issuer: DJK

Look at the easy version before watching the hard version

Title description:

Compared with the simple version, the difference is that the length of the string and the total number of operations have changed.

Ideas:

Give one of the construction methods.

Since the operation is performed on the prefix, it is easy to think of matching two 01 strings from the back to the front. When the s string and the t string, the s string and the t strings string and t string are in positioniiWhen i is different, perform operationiii , but when the operation iiis executedAfter i ,s string and t string s string and t stringThe strings s and t are at positioniii still may not match, so we need to preprocesssss string, let it all become0 00 or1 11 , so that operationiiAfter i , it must match.

Easy to find, operate at most 2 ∗ n 2*n2n times (preprocessing at mostnnn times, the matching process from back to front is at mostnnn times).

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
//#define int ll
#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define endl '\n'
#define pii pair<int,int>

const int maxn = 1e6 + 5;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const double eps = 1e-4;
int n, sum;
string s1, s2;
char ch;
int ans[maxn];

int main()
{
    
    
    io;
    //freopen("20.in", "r", stdin);
    //freopen("20.out", "w", stdout);
    cin >> s1 >> s2;
    n = s1.size();
    s1 = '$' + s1;
    s2 = '$' + s2;
    sum = 0;
    for(int i = 2; i <= n; ++i)
    {
    
    
        if(s1[i] != s1[i - 1])
            ans[++sum] = i - 1;
    }
    ch = s1[n] - '0';
    for(int i = n; i > 0; --i)
    {
    
    
        if(ch != (s2[i] - '0'))
        {
    
    
            ans[++sum] = i;
            ch = 1 - ch;
        }
    }
    cout << sum;
    for(int i = 1; i <= sum; ++i) cout << ' ' << ans[i];
    cout << '\n';
    return 0;
}

Problem G A+B Problem [ull natural overflow]

Issuer: NXY

a+b, a+b, a+b, a+b, a+b, a+b, a+b, a+b, a+b, a+b, a+b, a+b, a+ b, a+b, a+b, a+b, a+b, a+b, a+b, a+b, a+b, a+b, a+b, a+b, a+b a+b a+b a+b a+b a+b a+b

At the beginning of this question, NXY wanted to test that the natural overflow of ull is equal to taking the modulus of 2 64 , so the title of the question was originally called **"Natural overflow is nothing!"**, but some dogs suggested changing the numbers of a and b The length was changed to 1e5, which made NXY get stuck in py (

Ideas:

There are two knowledge points that need to be used:

  • unsigned long longNatural overflow is equivalent to 2 64 2^{64}26 4 modulo, that is to say,there is nothing wrong with natural overflow!
  • ( a × b + c )   %   p = ( ( a × b )   %   p + c   %   p )   %   p (a\times b + c)\ \%\ p = ((a\times b)\ \%\ p+c\ \%\ p)\ \%\ p (a×b+c) % p=((a×b) % p+c % p) % p

Therefore, we only need to input the number aaa decomposes intoa = x ∗ 10 + ca = x * 10 + ca=x10+c can

NXY is stuck on python

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

#define endl '\n'
#define inf 0x3f3f3f3f
#define mod7 1000000007
#define mod9 998244353
#define m_p(a,b) make_pair(a, b)
#define mem(a,b) memset((a),(b),sizeof(a))
#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;
typedef pair <int,int> pii;

#define MAX 300000 + 50
string s;
ull a, b;

void work(){
    
    
    cin >> s;
    a = b = 0;
    for(auto x : s){
    
    
        a = a * 10 + (ull)(x - '0');
    }
    cin >> s;
    for(auto x : s){
    
    
        b = b * 10 + (ull)(x - '0');
    }
    cout << (ull)(a+b) <<endl;
}


int main(){
    
    
    io;
    work();
    return 0;
}

Problem H Liu Yuxin's Color Map 【Pólya Counting】

Issuer: BHQ

Anti-AK problem

Title description:

a bracelet with nnn beads, there arenn colors, color each bead. How many different dyeing methods are there. Due to the large number of plans, please contact998244353 9982443539 9 8 2 4 4 3 5 3 model.

answer

The naked question of Pólya counting is difficult, if you want to understand, you can understand it yourself.

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
#define ll long long
const int N = 1e4+5;
const ll mod = 998244353;

ll qpow(ll a, ll b, ll c){
    
    
    a %= c;
    ll ans = 1;
    while(b){
    
    
        if(b & 1)
            ans = (ans * a) % c;
        a = (a * a) % c;
        b >>= 1;
    }
    return ans;
}

ll phi(ll n){
    
    
    ll ans = n;
    for(int i = 2; i*i <= n; ++i){
    
    
        if(n % i == 0){
    
    
            ans = ans / i * (i-1);
            while(n % i == 0)
                n /= i;
        }
    }
    if(n != 1)
        ans = ans / n * (n-1);
    return ans;
}

void solve(ll n){
    
    
    if(n == 1)
        cout << 1 << '\n';
    else
    {
    
    
        ll ans = 0;
        for(int i = 1; i * i <= n; ++i){
    
    
            if(n % i == 0){
    
    
                if(i * i == n)
                    ans = (ans + (phi(n/i) * qpow(n, i, mod) % mod)) % mod;
                else{
    
    
                    ans = (ans + (phi(i) * qpow(n, n/i, mod) % mod)) % mod;
                    ans = (ans + (phi(n/i) * qpow(n, i, mod) % mod)) % mod;
                }
            }
        }
        cout << (ans * qpow(n, mod-2, mod)) % mod << '\n';
    }
}

int main()
{
    
    
	std::ios::sync_with_stdio(false);
    ll n;
    cin >> n;
    solve(n);
	return 0;
}

Problem I WWW's Grocery Store【Simulation】

Issuer: WYY

Title description:

M sales records, each sales record consists of item name, receiving place, and sales quantity.

Please perform statistics and output according to the following rules: items are classified according to the place of receipt, and the number of sales is combined, the place of receipt is arranged in lexicographical order, and the items in the same place of receipt are arranged in lexicographical order.

Ideas:

It's a simple mock question, nothing interesting

#pragma GCC optimize(3)
#include <bits/stdc++.h>
using namespace std;

#define endl '\n'
#define inf 0x3f3f3f3f
#define mod7 1000000007
#define mod9 998244353
#define m_p(a,b) make_pair(a, b)
#define mem(a,b) memset((a),(b),sizeof(a))
#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
typedef long long ll;
typedef pair <int,int> pii;

#define MAX 300000 + 50
int n, m, k, op;
int x, y, z;
string s, t;

struct ran{
    
    
    string s;
    map<string, int>mp;
}tr[105];

void work(){
    
    
    cin >> n;
    for(int i = 1; i <= 100;++i)tr[i].mp.clear();
    map<string, int>mp;
    int tot = 0;
    for(int i = 1; i <= n; ++i){
    
    
        cin >> s >> t >> x;
        if(!mp.count(t))mp[t] = ++tot;
        tr[mp[t]].s = t;
        tr[mp[t]].mp[s]+=x;
    }
    for(auto [x,y] : mp){
    
    
        cout << tr[y].s << endl;
        cout << "--------------------\n";
        for(auto [u, v] : tr[y].mp){
    
    
            cout << "    ";
            cout << u << "(" <<v <<")\n";
        }
        cout << "--------------------\n";
    }
    
}

int main(){
    
    
    io;
    int tt;cin>>tt;
    for(int _t = 1; _t <= tt; ++_t){
    
    
        work();
        if(_t != tt)cout << endl;
    }
    return 0;
}

Problem J to play Pokémon~ [dp+line segment tree]

Issuer: DJK

Title description:

Breaking away from the background of the question and simply considering the interval operation, I found that the meaning of the question is as follows:

Given you a length n ( 1 ≤ n ≤ 5 ∗ 1 0 5 ) n(1≤n≤5*10^5)n(1n5105 )arrays. You need to divide it into several consecutive subintervals, and the weight of each interval is as follows:

  • If the interval sum is greater than 0, it is the interval length
  • If the interval sum is equal to 0, it is 0
  • If the interval sum is less than 0, it is the opposite number of the interval length

Expressed in a formula: val [ l , r ] = sign ( sum [ l , r ] ) ∗ ( r − l + 1 ) val[l,r] = sign(sum[l,r]) * (r - l + 1)va l [ l , _r]=sign(sum[l,r])(rl+1 ) ( val [ l , r ] represents the weight of the interval [ l , r ], the sign function is the same as the f function in the original question, and the sum [ l , r ] is also the same) (val[l,r] represents the interval [l ,r], the sign function is the same as the f function in the original question, and the sum[l,r] is also the same)( v a l [ l ,r ] means interval [ l ,r ] weight , _ _The s i g n function is the same as the f function in the original question , s u m [ l ,r ] is also the same )

Ask what is the maximum weight sum of the sub-intervals you have divided, and whether it is greater than or equal to HHH

train of thought

Data structure optimization DP

We first consider the brute force solution.

define dp[ i ] dp[i]dp[i] [ 1 , i ] [1,i] [1,i ] in the maximum weight sum, it is easy to find that it can beO ( n ) O(n)O ( n ) transfer, overall complexity requiresO ( n 2 ) O(n^2)O ( n2)

转移方程: d p [ i ] = m a x ( d p [ i ] , d p [ j ] + s i g n ( s u m [ j + 1 , i ] ) ∗ ( i − ( j + 1 ) + 1 ) ) 其 中 ( 0 ≤ j < i ) dp[i] = max(dp[i], dp[j] + sign(sum[j+1,i]) * (i-(j+1)+1)) 其中(0≤j<i) dp[i]=max(dp[i],dp[j]+sign(sum[j+1,i])(i(j+1)+1 ) ) where ( 0j<i)

The complexity is too high, we consider optimization.

according to sign signThe value classification of s i g n function is discussed, and the transfer equation is simplified:

d p [ i ] = m a x ( d p [ i ] , d p [ j ] + s i g n ( s u m [ i ] − s u m [ j ] ) ∗ ( i − j ) ) dp[i] = max(dp[i],dp[j]+sign(sum[i]-sum[j])*(i-j)) dp[i]=max(dp[i],dp[j]+sign(sum[i]sum[j])(ij))

s u m [ i ] = = s u m [ j ] sum[i]==sum[j] sum[i]==sum[j], d p [ i ] = m a x ( d p [ j ] ) dp[i] = max(dp[j]) dp[i]=max(dp[j])

s u m [ i ] > s u m [ j ] sum[i] > sum[j] sum[i]>sum[j], d p [ i ] = m a x ( d p [ j ] − j + i ) dp[i] = max(dp[j] - j +i) dp[i]=max(dp[j]j+i)

s u m [ i ] < s u m [ j ] sum[i] < sum[j] sum[i]<sum[j], d p [ i ] = m a x ( d p [ j ] + j − i ) dp[i] = max(dp[j] + j - i) dp[i]=max(dp[j]+ji)

We only need to ask for the corresponding max max in the above three casesm a x , then these three values ​​takemax maxMax can be .

It is easy to find that it needs a data structure that supports single-point modification + range query and is not too complicated to maintain.

The method is to preprocess the prefix sum, then discretize, and then build a line segment tree according to the prefix sum (other data structures that meet the conditions are acceptable).

That is, the subscript of the line segment tree means sum [ j ] sum[j]s u m [ j ] , the above three maximum values ​​are respectively passed toquery ( sum [ i ] , sum [ i ] ) query(sum[i],sum[i])query(sum[i],sum[i]), q u e r y ( 1 , s u m [ i ] − 1 ) query(1, sum[i]-1) query(1,sum[i]1), q u e r y ( s u m [ i ] + 1 , n ) query(sum[i] + 1, n) query(sum[i]+1,n ) obtained.

Complexity O ( nlogn ) O(nlogn)O(nlogn)

In addition, the reason to try violence in the prompt is to write the violence transfer equation first, so as to facilitate the observation and optimization later.

5 e 5 5e5 It is impossible to pass the data volume violence of 5 e 5 .

The code optimized using the line segment tree is given below.

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
#define int ll
#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define endl '\n'
#define itt set<node>::iterator
#define pii pair<int,int>

const int inf = 0x3f3f3f3f;
const int maxn = 5e5 + 5;
int t, n, x, h;
int sum[maxn];
int dp[maxn];
vector<int> vt;
struct node
{
    
    
    int l, r;
    int dp, dp1, dp2;//维护上述的三个最大值

    int mid()
    {
    
    
        return (l + r) >> 1;
    }

    void print()
    {
    
    
        cout << l << ' ' << r << ' ' << dp << ' ' << dp1 << ' ' << dp2 << '\n';
    }
} tree[maxn<<2];

void pushup(node &p, node &le, node &ri)
{
    
    
    p.l = le.l;
    p.r = ri.r;
    p.dp = max(le.dp, ri.dp);
    p.dp1 = max(le.dp1, ri.dp1);
    p.dp2 = max(le.dp2, ri.dp2);
}

void pushup(int p)
{
    
    
    pushup(tree[p], tree[p<<1], tree[p<<1|1]);
}

void build(int p, int l, int r)
{
    
    
    tree[p].l = l;
    tree[p].r = r;

    if(l == r)
    {
    
    
        tree[p].dp = tree[p].dp1 = tree[p].dp2 = -inf;
        return ;
    }

    int mid = tree[p].mid();
    build(p<<1, l, mid);
    build(p<<1|1, mid + 1, r);
    pushup(p);
}

void updata(int p, int pos, int dp, int id)
{
    
    
    if(tree[p].l == tree[p].r)
    {
    
    
        tree[p].dp = max(tree[p].dp, dp);
        tree[p].dp1 = max(tree[p].dp1, dp - id);
        tree[p].dp2 = max(tree[p].dp2, dp + id);
        return ;
    }

    int mid = tree[p].mid();
    if(pos <= mid) updata(p<<1, pos, dp, id);
    else updata(p<<1|1, pos, dp, id);
    pushup(p);
}

node query(int p, int l, int r)
{
    
    
    if(l > r) return {
    
    -inf, -inf, -inf, -inf};
    if(l <= tree[p].l && tree[p].r <= r) return tree[p];

    int mid = tree[p].mid();
    if(mid >= r) return query(p<<1, l, r);
    else if(mid < l) return query(p<<1|1, l, r);
    else
    {
    
    
        node le = query(p<<1, l, r);
        node ri = query(p<<1|1, l, r);
        node res;
        pushup(res, le, ri);
        return res;
    }
}

void work()
{
    
    
    vt.clear();
    cin >> n >> h;
    for(int i = 1; i <= n; ++i)
    {
    
    
        cin >> x;
        sum[i] = sum[i - 1] + x;
        vt.push_back(sum[i]);
        dp[i] = 0;
    }
    vt.push_back(0);

    sort(vt.begin(), vt.end());
    vt.erase(unique(vt.begin(), vt.end()), vt.end());

    build(1, 1, vt.size());

    node pp;
    int mx1, mx2, mx3, pos;
    pos = lower_bound(vt.begin(), vt.end(), 0) - vt.begin() + 1;
    updata(1, pos, 0, 0);
    for(int i = 1; i <= n; ++i)
    {
    
    
        pos = lower_bound(vt.begin(), vt.end(), sum[i]) - vt.begin() + 1;
        mx1 = query(1, 1, pos - 1).dp1;
        mx2 = query(1, pos, pos).dp;
        mx3 = query(1, pos + 1, vt.size()).dp2;
        dp[i] = max(mx1 + i, max(mx2, mx3 - i));
        updata(1, pos, dp[i], i);
    }

    cout << dp[n] << ' ' << (dp[n] >= h) << '\n';
}

signed main()
{
    
    
    io;
    cin >> t;
    while(t--) work();
    return 0;
}

Problem K escapes the virtual circle! 【bfs】

Issuer: LYJ

I came up with a bfs template question, no one did it, so sad, I wrote the background of the question for a long time, no one read it, so sad, even added a small easter egg during the competition, no one read it, so sad

Although

Title description:

n points, m edges, undirected graph

Given p starting points and q ending points, what is the shortest distance you need to start from any starting point and reach any end point?

Ideas:

Just bfs, put all the starting points into the queue, and then record q end points. When running, the first end point that appears is the shortest.

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

#define endl '\n'
#define inf 0x3f3f3f3f
#define mod7 1000000007
#define mod9 998244353
#define m_p(a,b) make_pair(a, b)
#define mem(a,b) memset((a),(b),sizeof(a))
#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
typedef long long ll;
typedef pair <int,int> pii;

#define MAX 1000000 + 50
int n, m, k, x, y, a, b;
vector<int>G[MAX];

queue<int>q;
set<int>se;
int dis[MAX];

void bfs(){
    
    
    while(!q.empty()){
    
    
        int u = q.front();q.pop();
        if(se.count(u)){
    
    
            cout << dis[u] << endl;
            return;
        }
        for(auto v : G[u]){
    
    
            if(dis[v] != inf)continue;
            dis[v] = dis[u] + 1;
            q.push(v);
        }
    }
    cout << "N0" << endl;
}

void work(){
    
    
    cin >> n >> m;
    for(int i = 1; i <= m; ++i){
    
    
        cin >> x >> y;
        G[x].push_back(y);
        G[y].push_back(x);
    }
    mem(dis, inf);
    cin >> a >> b;
    for(int i = 1; i <= a; ++i){
    
    
        cin >> x;
        q.push(x);
        dis[x] = 0;
    }
    for(int i = 1; i <= b; ++i){
    
    
        cin >> x;
        se.insert(x);
    }
    bfs();
    
}

int main(){
    
    
    work();
    return 0;
}

Problem L Oier who generates electricity for love【Simple expectation】

Issuer: WWY

Check-in questions, no one wrote, 6

Title description:

We can understand the topic as flipping a coin, and ask how many times we expect to flip it so that the number of heads isn

Ideas:

Obviously, the expected 2number of throws can make the number of heads up is 1

The expectation of getting n heads is 2*ntimes

So the output 2*nwould be

Here is a very interesting thing:

image-20221204200818664

In 16 minutes, someone saw this question and wrote the correct solution, but because he didn't write the input, he hung up, (laughing to death

#pragma GCC optimize(3)
#include <bits/stdc++.h>
using namespace std;

#define endl '\n'
#define inf 0x3f3f3f3f
#define mod7 1000000007
#define mod9 998244353
#define m_p(a,b) make_pair(a, b)
#define mem(a,b) memset((a),(b),sizeof(a))
#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
typedef long long ll;
typedef pair <int,int> pii;

#define MAX 300000 + 50
int n, m, k, x;
int tr[MAX];

void work(){
    
    
    cin >> n;
    cout << 2 * n << endl;
}


int main(){
    
    
    io;
    work();
    return 0;
}

Problem M doesn't care about freshman life or death [Category Discussion]

Issuer: LYJ

When writing the question, I asked five or six questions before this question, and there was no check-in question, so I put a small discussion question

Title description:

You are at position 0, the target is position x, there is a door at position y, and there is a key at position z. Ask how many steps you need to walk at least to get to x. If you can’t get there, output -1

Ideas:

Sign the question, simply classify it, it’s not interesting

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

#define endl '\n'
#define inf 0x3f3f3f3f
#define mod7 1000000007
#define mod9 998244353
#define m_p(a,b) make_pair(a, b)
#define mem(a,b) memset((a),(b),sizeof(a))
#define io ios::sync_with_stdio(false)
#define debug(a) cout << "Debuging...|" << #a << ": " << a << "\n";
typedef long long ll;
typedef pair <int,int> pii;

#define MAX 300000 + 50
int x, y, z;

void work(){
    
    
    cin >> x >> y >> z;
    if(x == 0){
    
    
        cout << 0 << endl;
    }
    else if(x > 0){
    
    
        if(y < 0 || y > x)cout << x << endl;
        else {
    
    
            if(z > y)cout << "BLEACH yyds" << endl;
            else{
    
    
                if(z > 0)cout << x << endl;
                else cout << -z*2 + x << endl;
            }
        }
    }
    else{
    
    
        if(y < x || y > 0)cout << -x << endl;
        else{
    
    
            if(z < y)cout << "BLEACH yyds" << endl;
            else {
    
    
                if(z > 0)cout << 2*z - x << endl;
                else cout << -x << endl;
            }
        }
    }
}


int main(){
    
    
    io;
    work();
    return 0;
}

Problem N Taki 1000 (easy version) 【Construction】

Issuer: DJK

Title description:

Given you two strings s , ts,ts,t , according to the given mode of operation, issss string becomesttt string, required in3 ∗ n 3*n3Complete within n times ( nnn is the length of the string).

Ideas:

Give one of the construction methods.

We hope that when s string and t string s string and t strings string and t string are in positioniiWhen i is different, we want to negate theiii elements without affecting other elements, soO ( n ) O(n)O ( n ) traversal once.

It is easy to find that negation and inversion both have a characteristic. That is, to invert a string of 01 or reverse an even number of times, the string remains unchanged.

From this, we can realize the inversion of the iii positions without affecting other elements.

When s string and t string s string and t strings string and t string are in positioniiWhen i is different, perform the following operations:

  • perform operation iii
  • Execute operation 1 11
  • perform operation iii

It can be found that at most 3 ∗ n 3*n is required3n times, satisfy the meaning of the question.

code:

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
#define int ll
#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define endl '\n'
#define itt set<node>::iterator
#define pii pair<int,int>

const int inf = 0x3f3f3f3f;
const int maxn = 5e5 + 5;
int n;
string s, t;
int ans[3005];
int sum;

signed main()
{
    
    
    io;
    cin >> s >> t;

    n = s.size();
    sum = 0;
    for(int i = 0; i < n; ++i)
    {
    
    
        if(s[i] != t[i])
        {
    
    
            ans[++sum] = i + 1;
            ans[++sum] = 1;
            ans[++sum] = i + 1;
        }
    }

    cout << sum << ' ';
    for(int i = 1; i <= sum; ++i) cout << ans[i] << ' ';
    return 0;
}

Summarize

From the situation of the questions, many sign-in questions are not read or done. Compared with offline competitions, there is a big gap. I ran to play, this is not good...

Guess you like

Origin blog.csdn.net/weixin_51216553/article/details/128176836