Loading

Loading

2022CCPC女生专场 vp记录

2026/9/28 晚~9/29早

省流:单挑过了6题,但罚时太多没够到金牌线。L题和I题没做出来有点自责,但体感比2024女赛舒适(?

过题顺序:C->E->A->G->H->J

L的线段树还是要加油啊。K的FFT又是怎么看出来的。I 的字符串串我也不会写,F的位运算性质还是盯不出来。呜呜呜。

(恶魔低语)

C 测量学

无脑小签到

#include<bits/stdc++.h>
using namespace std;
int n;
double R,ci;
double r[100010],t[100010];
int main()
{
	cin>>n>>R>>ci;
	ci=min(ci,2*3.1415926-ci);
	for(int i=1;i<=n;i++) cin>>r[i],t[i]=ci*r[i]+2*(R-r[i]);
	t[0]=2*R;
	sort(t,t+n+1);
	double dis=min(t[0],ci*R);
	printf("%.6lf",dis);
	return 0;
}

E 睡觉

还是小签到,呃呃呃qwq我太粗心了,好多边界没考虑到被罚时了5次...

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll T,x,t,k,n,d;
ll a[200010],b[200010],s[200010];
int main()
{
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	cin>>T;
	while(T--)
	{
		//连续t秒小于等于k
		cin>>x>>t>>k>>n>>d;

		s[0]=0;
		ll tmp=0;
		bool flag=0;
		ll maxt=-0x3f3f3f3f;
		for(ll i=1;i<=2*n;i++)
		{
			if(i<=n)
			{
				cin>>a[i];
				if(a[i]<=d) b[i]=-1;
				else b[i]=1;
				
				s[i]=s[i-1]+b[i];
				
				if(s[i]+x<=k)
				{
					tmp++;
				}else{
					tmp=0;
				}
				if(tmp==t){
					flag=1;
				}
			}else{
				s[i]=s[i-1]+b[i-n];
				if(s[i]+x<=k)
				{
					tmp++;
				}else{
					tmp=0;
				}
				if(tmp==t){
					flag=1;
				}
			}
			maxt=max(maxt,tmp);
		}
		if(flag||s[n]<0||maxt==2*n){
			cout<<"YES"<<endl;
		}else{
			cout<<"NO"<<endl;
		}
	}
	
	return 0;
}

A. 减肥计划

用队列模拟即可

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll n,k; ll a[1000010];
int main(){ 
	ios::sync_with_stdio(false); 
	cin.tie(nullptr);
	 cin>>n>>k;
	 deque<ll> q;
	 ll mx=0;
	 for(ll i=1;i<=n;i++){ cin>>a[i]; q.push_back(i); mx=max(mx,a[i]); }
	 if(n==1){ cout<<1<<'\n'; return 0; }
	 k=min(k,n-1);            
	 ll tmp=0;             
	 while(1){
	   ll x=q[0], y=q[1];
	   q.pop_front(); q.pop_front();
	   if(a[x]>=a[y]){ tmp++; q.push_front(x); q.push_back(y); }
	   else { tmp=1; q.push_front(y); q.push_back(x); }
	   if(tmp==k || a[q[0]]==mx){ cout<<q[0]<<'\n'; break; }
	 }
	 return 0; 
 }

G 排队打卡

分别用begin和end来记录每一秒的开始和结束,过程就变得很清晰了。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll n,t;
ll m,k;
struct p{
	ll time,pp;
}a[500010];
bool cmp(p x,p y)
{
	return x.time<y.time;
}

ll bg[500010],ed[500010];
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cin>>t>>n>>m>>k;
	for(ll i=1;i<=m;i++)
	{
		cin>>a[i].time>>a[i].pp;
	}
	sort(a+1,a+1+m,cmp);

	for(ll i=1;i<=m;i++)
	{
		ll prev_time = (i==1 ? -1 : a[i-1].time);
		ll e_prev = (i==1 ? 0 : ed[i-1]);
		__int128 dec = (__int128)(a[i].time - prev_time - 1) * k;
		ll e_before = (dec >= e_prev ? 0 : e_prev - (ll)dec);
		bg[i] = e_before + a[i].pp;
		ed[i] = (bg[i] <= k ? 0 : bg[i] - k);
	}

	ll q_t = 0;
	{
		ll e_prev = 0, p_prev = -1;
		for(ll i=1;i<=m;i++){
			if(a[i].time < t){ e_prev = ed[i]; p_prev = a[i].time; }
			else break;
		}
		__int128 dec = (__int128)(t - p_prev - 1) * k;
		q_t = (dec >= e_prev ? 0 : e_prev - (ll)dec);
	}
	if(q_t!=n){
		cout<<"Wrong Record";
		return 0;
	}

	ll min_time=(ll)4e18,indx=-1;
	for(ll i=1;i<=m;i++)
	{
		if(a[i].time <= t) continue;
		ll wait = (bg[i] + 1 + k - 1) / k;
		if(wait<=min_time)
		{
			min_time=wait;
			indx=a[i].time;
		}
	}
	cout<<indx<<' '<<min_time;
	return 0;
}

H 提瓦特之旅

很有意思的一道题目^~^

问:带边权的无向图,从1出发,每到第 \(i\) 个位置代价加入 \(w_i\) ,问从 1 到 \(t\) 的最小代价。

由于n的数据范围很小,所以我们可以用 \(O(n*m)\) 的思路进行预处理。

开一个二维数组,第一维记录当前是走到的第几个节点,第二维记录当前在第几个节点。那么对于u,v,c,(起点终点边权)我们可以列出:

\[f[k][u]=min(f[k][u],f[k-1][v]+c) \]

\[f[k][v]=min(f[k][v],f[k-1][u]+c) \]

由于从1出发,那么需要初始化 \(f[0][1]=0\),其他全为INF

然后对于每一组查询,我们只需要记录 \(w_i\) 的前缀和即可求得结果,复杂度 \(O(n*q)\)

设 \(s[i]\) 为 \(w[i]\) 的前缀和数组,minn 为答案。

\[minn=min(minn,f[k][t]+s[k]) \]

完整代码:

(由于不开long long wa了一次,不开快读又t了一次qwq)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll INF=0x3f3f3f3f3f3f3f3f,N=100010;
ll eu[N],ev[N],ec[N];
ll f[510][510];
ll n,m,q,t;
ll w[N];
int main()
{
  	ios::sync_with_stdio(false);
    cin.tie(nullptr);  
	cin>>n>>m;
	
	ll u,v,c;
	for(int i=1;i<=m;i++)
	{
		cin>>u>>v>>c;
		eu[i]=u,ev[i]=v,ec[i]=c;
	}
	
	for(int i=0;i<=501;i++)
	{
		for(int j=0;j<=501;j++)
		{
			f[i][j]=INF;
		}
	}
	f[0][1]=0;
	for(int k=1;k<n;k++)
	{
		for(int i=1;i<=m;i++)
		{
			u=eu[i],v=ev[i],c=ec[i];
			if(f[k-1][v]!=INF)
			f[k][u]=min(f[k][u],f[k-1][v]+c);
			if(f[k-1][u]!=INF)
			f[k][v]=min(f[k][v],f[k-1][u]+c);
		}
	}
	cin>>q;
	
	while(q--)
	{
		ll s[510],minn=INF;
		s[0]=0;
		cin>>t;
		for(int i=1;i<n;i++)
		{
			cin>>w[i];
			s[i]=s[i-1]+w[i];
		}
		for(int k=0;k<n;k++)
		{
			minn=min(minn,f[k][t]+s[k]);
		}
		cout<<minn<<endl;
	}
	return 0;
}

J 瑞士轮

熟悉瑞士轮的宝宝都知道,连续的四个队必然产生 2-0,2-1,1-2,0-2四种情况。

那我们把所有的队全部每四个分为一组再枚举就可以了~

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll MOD=998244353;
ll a[40],w[40][40];
ll p20[40],p02[40],pad[40];

ll qpow(ll x,ll y=MOD-2){
    ll r=1;
    while(y){
        if(y&1) r=r*x%MOD;
        x=x*x%MOD;
        y>>=1;
    }
    return r;
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    for(int i=1;i<=32;i++) cin>>a[i];
    for(int i=1;i<=32;i++)
        for(int j=1;j<=32;j++){
            if(i==j) continue;
            w[i][j]=a[i]*qpow((a[i]+a[j])%MOD)%MOD;
        }
    // 8组,每组4队
    for(int b=0;b<8;b++){
        int t0=b*4+1,t1=b*4+2,t2=b*4+3,t3=b*4+4;
        int A[2]={t0,t1},B[2]={t2,t3};
        for(int i=0;i<2;i++)for(int j=0;j<2;j++){
            int w0=A[i],l0=A[1-i];
            int w1=B[j],l1=B[1-j];
            ll path=w[w0][l0]*w[w1][l1]%MOD;
            int U[2]={w0,w1},L[2]={l0,l1};
            for(int u=0;u<2;u++)for(int l=0;l<2;l++){
                int uw=U[u],ul=U[1-u];
                int win=L[l],lose=L[1-l];
                ll p2=path*w[uw][ul]%MOD*w[win][lose]%MOD;
                p20[uw]=(p20[uw]+p2)%MOD;
                pad[uw]=(pad[uw]+p2)%MOD;
                p02[lose]=(p02[lose]+p2)%MOD;
                ll pr=w[ul][win];
                pad[ul]=(pad[ul]+p2*pr)%MOD;
                pad[win]=(pad[win]+p2*((1-pr+MOD)%MOD))%MOD;
            }
        }
    }
    int m;cin>>m;
    while(m--){
        int b[10];
        for(int i=1;i<=9;i++){cin>>b[i];}
        ll ans=(p20[b[1]]+p02[b[2]])%MOD;
        for(int i=3;i<=9;i++) ans=(ans+pad[b[i]])%MOD;
        cout<<ans<<'\n';
    }
    return 0;
}

posted @ 2026-09-29 12:58  Miya555  阅读(12)  评论(0)    收藏  举报