CSP-S模拟40

CSP-S模拟40

A. 公约数神庙 (gcd)

八倍常数 \(O(\frac{n^2}{w})\) 可以 \(80ms\) 通过本题。

直接按照不带修追忆做 DAG 可达性然后空间爆炸。

发现 1000 以内质数有 168 个。而且 1000 以内的数最多有 4 个质因数。

那么改变策略,只记录每个质数可到的点集合。

先离线每个询问,对于每个左端点存询问右端点,再从后往前做,每次到一个位置先更改这个数的所有质因数的可达点集为这个数的所有质因数的点集的或,在查询以该点为区间左端点的所有询问的右端点可否到达。

特判以 0 为跳板直接可以跳到答案,1 无法跳到除自身之外任意地方。

Code:

#include <bits/stdc++.h>
// #define int long long

using namespace std;

const int Size = (1 << 20) + 1;
char buf[Size], *p1 = buf, *p2 = buf;
char buffer[Size];
int op1 = -1;
const int op2 = Size - 1;
#define getchar()                                                          \
    (tt == ss && (tt = (ss = In) + fread(In, 1, 1 << 20, stdin), ss == tt) \
         ? EOF                                                             \
         : *ss++)
char In[1 << 20], *ss = In, *tt = In;
inline int read()
{
    int x = 0, c = getchar(), f = 0;
    for (; c > '9' || c < '0'; f = c == '-', c = getchar())
        ;
    for (; c >= '0' && c <= '9'; c = getchar())
        x = (x << 1) + (x << 3) + (c ^ 48);
    return f ? -x : x;
}
inline void write(int x)
{
    if (x < 0)
        x = -x, putchar('-');
    if (x > 9)
        write(x / 10);
    putchar(x % 10 + '0');
}

// bitset<N>

// #ifndef ONLINE_JUDGE
// #define ONLINE_JUDGE
// #endif

// int fa[1<<20];
// int find(int x)
// {
// 	if(x==fa[x]) return x;
// 	return fa[x]=find(fa[x]);
// }

// const int N=1e5+5;
// struct Node{
// 	int to,id;
// };
// vector<Node> v[N];
// int lst[N];
// int ans[N];

// void chai(int x,int p)
// {
// 	bool f=0;
// 	if(p==2||p==7) f=1;
// 	for(int i=2;i*i<=x;i++)
// 	{
// 		if(x%i==0)
// 		{
// 			if(f) cout<<i<<" ";
// 			while(x%i==0) x/=i;
// 			if(lst[i]>0) fa[find(p)]=find(lst[i]);
// 			lst[i]=p;
// 		}
// 	}
// 	if(x>1)
// 	{
// 		if(f) cout<<x<<" ";
// 		if(lst[x]>0) fa[find(p)]=find(lst[x]);
// 		lst[x]=p;
// 	}
// 	if(f) cout<<"\n";
// }

// int n,q;
// int a[1<<20];

const int N = 1e5 + 1;
int n, q;
int a[N];
bitset<N> b[170];
struct Node
{
    int to, id;
};
vector<Node> v[N];
bool cmp(Node x, Node y) { return x.to < y.to; }
int lst[N];
int ans[N];
bool cmp2(int x, int y)
{
    return lst[x] < lst[y];
}

int aa[100], top;
int id[1005];
int sum_0[N], sum_n0[N];
void chai(int x, int p)
{
    if (x == 0)
    {
        for (Node nw : v[p])
        {
            if (nw.to == p)
            {
                ans[nw.id] = 1;
            }
            else if (a[nw.to] != 1)
            {
                if (a[nw.to] == 0)
                    ans[nw.id] = sum_n0[nw.to] - sum_n0[p];
                else
                    ans[nw.id] = 1;
            }
        }

        for (int i = 1; i <= 168; i++)
            lst[i] = p;
        for (int i = 1; i <= 168; i++)
            for (int j = p; j < lst[0]; j++)
                b[i][j] = 1;
        lst[0] = p;
        return;
    }
    if (x == 1)
    {
        for (Node nw : v[p])
            ans[nw.id] = nw.to == p;
        return;
    }
    top = 0;
    // if(lst[0]!=n+1) aa[++top]=0;
    for (int i = 2; i * i <= x; i++)
    {
        if (x % i == 0)
        {
            aa[++top] = i;
            // return 0;
            while (x % i == 0)
                x /= i;
            // if(lst[i]>0) fa[find(p)]=find(lst[i]);
            // lst[i]=p;
        }
    }
    if (x > 1)
        aa[++top] = x;
    for (int i = 1; i <= top; i++)
        aa[i] = id[aa[i]];
    sort(aa + 1, aa + 1 + top, cmp2);

    for (int i = 2; i <= top; i++)
    {
        int nw = aa[i];
        if (lst[nw] > 0 && b[aa[1]][lst[nw]])
            continue;
        if (lst[nw] > 0)
            b[aa[1]] |= b[nw];
    }
    b[aa[1]][p] = 1;
    sort(v[p].begin(), v[p].end(), cmp);
    for (Node nw : v[p])
    {
        if (nw.to == p)
        {
            ans[nw.id] = 1;
        }
        else if (a[nw.to] != 1)
        {
            if (a[nw.to] == 0)
                ans[nw.id] = 1;
            else
                ans[nw.id] = b[aa[1]][nw.to];
        }
        
    }
    lst[aa[1]] = p;
    for (int i = 2; i <= top; i++)
    {
        int nw = aa[i];
        b[nw] = b[aa[1]];
        lst[nw] = p;
    }

    // return 1;
    // if(x>1)
    // {
    // 	if(lst[x]>0) fa[find(p)]=find(lst[x]);
    // 	lst[x]=p;
    // }
}

void init()
{
    // cout<<__gcd(5,0)<<"\n";
    bitset<1005> f;
    vector<int> v;
    for (int i = 2; i <= 1000; i++)
    {
        if (!f[i])
        {
            v.push_back(i);
            for (int j = i + i; j <= 1000; j += i)
                f[j] = 1;
        }
    }
    // cout<<v.size()<<endl;
    for (int i = 0; i < v.size(); i++)
        id[v[i]] = i + 1;
}

signed main()
{
    // #ifndef ONLINE_JUDGE
    freopen("gcd.in", "r", stdin);
    freopen("gcd.out", "w", stdout);
    init();
    n = read();
    q = read();
    memset(lst, -1, sizeof(lst));
    lst[0] = n + 1;
    for (int i = 1; i <= n; i++)
    {

        a[i] = read();
        sum_0[i] = sum_0[i - 1] + (a[i] == 0);
        sum_n0[i] = sum_n0[i - 1] + (a[i] >1);
    }

    // for (int i = 17; i <= 25;i++)
    // {
    //     cout << a[i] << " ";
    // }
    // cout << "\n";
    // // int tot=0;
    // for(int i=2;i<=1000;i++) tot+=chai(i,i);
    // cout<<tot;
    for (int i = 1; i <= q; i++)
    {
        int x = read(), y = read();
        if (x > y)
            swap(x, y);
        v[x].push_back({y, i});
    }
    // for(int i=1;i<=n+1;i++) fa[i]=i;
    for (int i = n; i >= 1; i--)
    {
        chai(a[i], i);
    }
    for (int i = 1; i <= q; i++)
    {
        if (ans[i])
            puts("Shi");
        else
            puts("Fou");
    }

    // #endif
    // mt19937_64 myrand(time(0));
    return 0;
}

B. 栈法师 (sort)

有 2n 次做法。

有 checker。

Code:

/*

checker.cpp: ( > O(n^2))

zao fu hou ren ^_^

*/

/*
#include<bits/stdc++.h>
#define int long long

using namespace std;

inline int read()
{
	int x=0,c=getchar(),f=0;
	for(;c>'9'||c<'0';f=c=='-',c=getchar());
	for(;c>='0'&&c<='9';c=getchar())
		x=(x<<1)+(x<<3)+(c^48);
	return f?-x:x;
}
inline void write(int x)
{
	if(x<0) x=-x,putchar('-');
	if(x>9)  write(x/10);
	putchar(x%10+'0');
}

// #ifndef ONLINE_JUDGE
// #define ONLINE_JUDGE
// #endif
int a[101][100001];
int n[101];

int s[3][1<<20],t[3];
int ans[1<<20],cnt;

bool check(int T)
{
    cout<<"Checking Test #"<<T<<", ";
    fflush(stdout);
    cnt=0;
    // t[1]=t[2]=0;
    memset(t,0,sizeof(t));
    int tot=read();
    tot=read();
    // cout<<tot<<" ";
    int nw=n[T];
    // cout<<n[T]<<"\n";
    for(int i=1;i<=tot;i++)
    {
        int op=read();
        if(op==1)
        {
            // cout<<"1: "<<i<<"\n";
            int b=read(),c=read();
            for(int kkk=1;kkk<=c;kkk++)
            {
                if(!nw) { cout<<"! in the 1 opreation, the num of [a] is none, "; return 0; }
                s[b][++t[b]]=a[T][nw];
                nw--;
            }
        }
        else if(op==2)
        {
            // if(i<=1028)cout<<i<<"\n";
            int b=read();
            if(t[b]==0)
            {
                { cout<<"! in the 2 opreation, [ the id="<<b<<" stack ] is none, "; return 0; }
            }
            ans[++cnt]=s[b][t[b]];
            t[b]--;
        }
        else if(op==3)
        {
            // if(i<=1028)cout<<i<<"\n";
            int b=read(),c=read(),d=read();
            for(int kkk=1;kkk<=d;kkk++)
            {
                if(t[b]==0)
                {
                { cout<<"! in the 3 opreation, [ the id="<<b<<" stack ] is none, "; return 0; }
                }
                t[c]++;
                s[c][t[c]]=s[b][t[b]];
                t[b]--;
            }

        }
        else { cout<<"! opreation illegal, "; return 0; }
    }
    for(int i=1;i<=n[T];i++) if(ans[i-1]>ans[i]) {cout<<"the answer is not sorted, retest failed, "; return 0;}
    return 1;
}

signed main()
{
	// #ifndef ONLINE_JUDGE
	freopen("sort.in","r",stdin);
    int T=read();
    for(int i=1;i<=T;i++)
    {
        n[i]=read();
        for(int j=1;j<=n[i];j++) a[i][j]=read();
    }
    fclose(stdin);
    cout<<endl;
	freopen("sort.out","r",stdin);
    for(int i=1;i<=T;i++)
    {
        bool nw=check(i);
        if(nw) { cout<<" : Accepted"; }
        else { cout<<" : Wrong Answer"; exit(0); }
        cout<<endl;
    }
    
	// #endif
	//mt19937_64 myrand(time(0));
	return 0;
}

*/




/*

---------------------------------------------------------------

*/



#include<bits/stdc++.h>
// #define int long long
#define getchar getchar_unlocked
#define putchar putchar_unlocked

using namespace std;

inline int read()
{
	int x=0,c=getchar(),f=0;
	for(;c>'9'||c<'0';f=c=='-',c=getchar());
	for(;c>='0'&&c<='9';c=getchar())
		x=(x<<1)+(x<<3)+(c^48);
	return f?-x:x;
}
short NUM_OUT[15],TOP=0;
inline void write(int x)
{
    TOP=0;
    while(x)
    {
        NUM_OUT[++TOP]=x%10;
        x/=10;
    }
    while(TOP)
    {
        // TOP--;
        putchar(NUM_OUT[TOP--]+'0');
    }
	// if(x<0) x=-x,putchar('-');
	// if(x>9)  write(x/10);
	// putchar(x%10+'0');
}

// #ifndef ONLINE_JUDGE
// #define ONLINE_JUDGE
// #endif
int n;
const int N=1e5+5;
int a[N];
int b[N],topb;
int sta[N],top;

struct Ans{
    int a,b,c,d;
};
Ans ans[N*5];
int tot=0;

void output_ans(int k)
{
    write(k);
    putchar('\n');
    write(tot);
    putchar('\n');
    for(int i=1;i<=tot;i++)
    {
        write(ans[i].a);
        putchar(' ');
        write(ans[i].b);
        putchar(' ');
        if(ans[i].c>0)
        {
            write(ans[i].c);
            putchar(' ');
        }

        if(ans[i].d>0)
        {
            write(ans[i].d);
            putchar(' ');
        }
        putchar('\n');
    }
}

int t[N];
int lowbit(int x) { return x&(-x); }
void Add(int x)
{
    int aaa=0;
    // return 0;
    // cerr<<x<<" "<<lim<<"\n";
    for(int i=x;i<=top;i+=lowbit(i)) t[i]++;
}
int Query(int r)
{
    // return 0;
    int ans=0;
    // cerr<<r<<"\n";
    for(int i=r;i>0;i-=lowbit(i)) ans+=t[i];
    // cerr<<r<<"\n";
    return ans;
}
vector<int> num[N]; 

void solve()
{
    tot=0;
    topb=1;
    top=0;
    n=read();
    for(int i=1;i<=n;i++) a[i]=read(),b[i]=a[i];
    sort(b+1,b+1+n);
    for(int i=n;i>=1;i--)
    {
        ans[++tot]={1,1,1,-1};
        sta[++top]=a[i];
        while(top&&sta[top]==b[topb])
        {
            top--;
            topb++;
            ans[++tot]={2,1,-1,-1};
        }
    }
    
    if(top==0)
    {
        output_ans(1);
        return;
    }
    else
    {
        vector<int> nww;
        reverse(sta+1,sta+top+1);
        for(int i=1;i<=top;i++) t[i]=0;
        // cerr<<"\n";
        for(int i=1;i<=top;i++)num[sta[i]].push_back(i),nww.push_back(sta[i]);
        nww.push_back(1e9);
        sort(nww.begin(),nww.end());
        // return;
        // for(int i=1;i<=100000;i++)
        for(int i=1;i<nww.size();i++)
        if(nww[i-1]!=nww[i])
        for(int p:num[nww[i-1]])
        {
            int dt=p-1-Query(p-1);
            if(dt) ans[++tot]={3,1,2,dt};
            ans[++tot]={2,1,-1,-1};
            if(dt) ans[++tot]={3,2,1,dt};
            Add(p);
        }
        for(int i=1;i<=top;i++) num[sta[i]].clear();

        output_ans(2);
    }
}

signed main()
{
	// #ifndef ONLINE_JUDGE
	freopen("sort.in","r",stdin);
	freopen("sort.out","w",stdout);

    int T=read();
    while(T--) solve();

	return 0;
}

C. 城堡考古 (decoration)

Code:


D. 生命之树 (dagger)

Code:


posted @ 2025-10-27 16:29  Wy_x  阅读(18)  评论(1)    收藏  举报