暑假集訓CSP提高模擬12

wlesq發表於2024-07-31

T1
image
這題千萬不要認為是莫反題
列舉質因子\(x,y\)\(x,y<=998\),對答案的貢獻為\(min(\lfloor{\frac{B}{x}}\rfloor,\lfloor{\frac{D}{y}}\rfloor)\),再容斥一下即可
MD最後答案要取模啊

點選檢視程式碼
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
using namespace std;
const int mod=1e9+7;
ll A,B,C,D;
inline ll solve(ll B,ll D)
{
	ll ans=0;
	for(ll x=1;x<=998;x++)
	{
		for(ll y=1;y<=998;y++)
		{
			if(x+y>999||x>B||y>D)break;
			if(__gcd(x,y)!=1)continue;
//			cout<<x<<" "<<y<<endl;
//			cout<<B/x+D/y<<endl;
			ans=((min(B/x,D/y))*(x+y)%mod+ans)%mod;
//			ans%=mod;
		}
	}
	return ans;
}
int main()
{
	speed();
	cin>>A>>B>>C>>D;
	ll ans=0;
//	cout<<solve(B,D)<<endl;
	cout<<((solve(B,D)+solve(A-1,C-1)-solve(A-1,D)-solve(B,C-1))%mod+mod)%mod<<endl;
	
	return 0;
}
/*
5 8 3 6

999999999999 1000000000000 999999999999 1000000000000
*/

T2
image
讀假題了,以為是一個一個換(MD我考試在幹什麼啊)
其實就是找行之間那些匹配,同理找列之間,我們發現是有傳遞性的,如\(1行可以與2行和3行匹配\),那無論\(2,3行\)可不可以直接交換,都有一種可以透過\(1\)讓他們交換位置

點選檢視程式碼
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define pb push_back
#define ull unsigned long long
using namespace std;
const int mod=998244353,N=55;
ll n,k,a[N][N];
ll jie[N],fa[N],cnt[N],cnt2[N];
int find(int x)
{
	if(fa[x]!=x)fa[x]=find(fa[x]);
	return fa[x];
}
int main()
{
	speed();
	// freopen("in.in","r",stdin);
	// freopen("out.out","w",stdout);
	cin>>n>>k;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
			cin>>a[i][j];
	}
	jie[0]=1;
	for(ll i=1;i<=n;i++)jie[i]=jie[i-1]*i%mod;
	for(int i=1;i<=n;i++)fa[i]=i;
	for(int i=1;i<=n;i++)
	{
		for(int j=i+1;j<=n;j++)
		{
			bool chk=1;
			for(int x=1;x<=n;x++)
				if(a[i][x]+a[j][x]>k){chk=0;break;}
			if(chk)
			{
				if(find(i)!=find(j))
				{
					fa[find(i)]=find(j);
				}
				// hang[i]++;
			}
		}
		// hang[i]++;
		// cout<<i<<" "<<hang[i]<<endl;
	}
	ll ans=1;
	for(int i=1;i<=n;i++)
	{
		cnt[find(i)]++;
	}
	for(int i=1;i<=n;i++)if(cnt[i])ans=ans*jie[cnt[i]]%mod;
	// 	cout<<endl;
	// cout<<han<<endl;
	for(int i=1;i<=n;i++)fa[i]=i;
	for(int i=1;i<=n;i++)
	{
		for(int j=i+1;j<=n;j++)
		{
			bool chk=1;
			for(int x=1;x<=n;x++)
				if(a[x][i]+a[x][j]>k){chk=0;break;}
			if(chk)
			{
				if(find(i)!=find(j))
				{
					fa[find(i)]=find(j);
				}
			}
		}
		// cout<<i<<" "<<lie[i]<<endl;
	}
	for(int i=1;i<=n;i++)
	{
		cnt2[find(i)]++;
	}
	for(int i=1;i<=n;i++)if(cnt2[i])ans=ans*jie[cnt2[i]]%mod;
	// for(int i=1;i<=n;i++)cout<<cnt2[i]<<" ";
	// 	cout<<endl;
	// if(!ans)
	// {
		// ans=jie[max(*max_element(cnt+1,cnt+1+n),*max_element(cnt2+1,cnt2+1+n))];
	// }
	cout<<ans<<endl;
	return 0;
}

T3
原題
image

記憶化搜尋
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#pragma GCC optimize(10086)
#define ull unsigned long long
using namespace std;
const int N = 255;
const ull B=233;
int T,n,r;
struct ac
{
	double p;ll val;
}a[N];
bool vis[N];
unordered_map <ull,map<int,double>> dp[2];
//ll dp[15][15][1<<10];
ull calc()
{
	ull ans=0;
	for(int i=1;i<=n;i++)
	{
		ll cnt=vis[i];
		ans=ans*B+cnt;
	}
	return ans;
}
double dfs(int cnt,ull tmp,bool f)
{
	if(!cnt)return 0.0;
	if(dp[f][tmp][cnt])return dp[f][tmp][cnt]; 
	double p=1,res=0.0;
	for(int i=1;i<=n;i++)
	{
		if(vis[i])continue;
		vis[i]=1;
		res+=p*a[i].p*(a[i].val+dfs(cnt-1,calc(),1));
		p*=(1.0-a[i].p);
		vis[i]=0;
	}
	res+=p*dfs(cnt-1,tmp,0);
//	cout<<tmp<<" "<<setprecision(6)<<fixed<<res<<endl;
	return dp[f][tmp][cnt]=res;
}
int main()
{
	speed();
//	freopen("T3.in","r",stdin);
	cin>>T;
	while(T--)
	{
		cin>>n>>r;	
		memset(vis,0,sizeof vis);
		memset(a,0,sizeof a);
//		memset(dp,0,sizeof dp);
		dp[1].clear();dp[0].clear();
		for(int i=1;i<=n;i++)
		{
			cin>>a[i].p>>a[i].val;
		}
		if(!r)
		{
			double p=1,res=0.0;
			for(int i=1;i<=n;i++)
			{
				if(vis[i])continue;
				vis[i]=1;
				res+=p*a[i].p;
				p*=(1.0-a[i].p);
				vis[i]=0;
			}
			res+=p;			
			cout<<0<<endl;
			continue;
		}

		cout<<setprecision(10)<<fixed<<dfs(r,0,1)<<endl;
//		break;
	}
	return 0;
}
/*
2 
10 5
0.5000 2 
0.3000 3 
0.9000 1
0.5000 2 
0.3000 3 
0.9000 1
0.5000 2 
0.3000 3 
0.9000 1
0.5000 2 
3 2 
0.5000 2 
0.3000 3 
0.9000 1
*/

正解,考慮設\(g_i\)表示修第\(i\)段水管的機率,則答案為\(ans=\sum g_ival_i\)
如何求\(g_i\)呢?,設\(f_{i,j}\)表示前\(i\)段內修復了\(j\)次的機率,顯然轉移就有當前位置修或不修(既不漏)

\[f_{i,j}=(i!=j)f_{i-1,j}\times (1-p_i)^{r-j}+(j\ne 0) f_{i-1,j-1}\times (1-(1-p_i)^{r-j+1}) \]

顯然有\(g_i=\sum_{j=0}^{min{(i-1,r)}}f_{i-1,j}\times [1-(1-p_i)^{r-j}]\)注意啊邊界,因為當前必須修
注意特判\(r=0\)的時候

點選檢視程式碼
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define pb push_back
#define ull unsigned long long
using namespace std;
const int N=355;
struct ac
{
	double p;ll val;
}a[N];
int T,n,r;
double f[N][N],g[N],qpow[N][N];
int main()
{
	speed();
	// freopen("in.in","r",stdin);
	// freopen("out.out","w",stdout);
	cin>>T;
	while(T--)
	{
		cin>>n>>r;
		if(!r)
		{
			cout<<0.00000000<<endl;
			continue;
		}
		memset(f,0,sizeof f);	
		memset(a,0,sizeof a);memset(g,0,sizeof g);
		for(int i=1;i<=n;i++)
		{
			cin>>a[i].p>>a[i].val;
			qpow[i][0]=1;
			for(int j=1;j<=r;j++)qpow[i][j]=qpow[i][j-1]*(1-a[i].p);
		}
		// f[1][0]=pow(1-a[1].p,r);
		// for(int i=2;i<=n;i++)f[i][0]=f[i-1][0]*pow(1-a[i].p,r);
		f[1][0]=qpow[1][r];f[1][1]=g[1]=1.0-qpow[1][r];
		for(int i=2;i<=n;i++)
		{
			for(int j=0;j<=min(i,r);j++)
			{		
				f[i][j]=(i!=j)*f[i-1][j]*qpow[i][r-j]+(j!=0)*f[i-1][j-1]*(1.0-qpow[i][r-j+1]);
			}
		}
		for(int i=2;i<=n;i++)
			for(int j=0;j<=min(i-1,r);j++)
				g[i]+=f[i-1][j]*(1.0-qpow[i][r-j]);
		double ans=0;
		for(int i=1;i<=n;i++)ans+=g[i]*a[i].val;
		cout<<setprecision(10)<<fixed<<ans<<endl;
	}
	return 0;
}

T4
分塊,deque可以直接訪問,服了
注意越界問題

點選檢視程式碼
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define pb push_back
#define ull unsigned long long
using namespace std;
const int N=1e5+5;
// #pragma GCC optimize(3)
int n,a[N],q,sq,bl[N],cnt[340][N];
int be[N],ed[N];
deque <int> dq[340];
void T()
{
	cout<<"*************"<<sq<<" "<<n/sq<<" "<<endl;
	for(int i=1;i<=sq;i++)
	{
		cout<<dq[i].size()<<endl;
		for(auto s:dq[i])cout<<s<<" ";
		cout<<endl;
	}
	cout<<endl;
}
void init()
{
	for(int i=1;i<=n;i++)
	{
		bl[i]=(i-1)/sq+1;
		be[i]=(bl[i]-1)*sq+1;
		ed[i]=min(n,bl[i]*sq);
	}
	// for(int i=1;i<=n;i++)
	// {
	// 	cout<<be[i]<<" "<<ed[i]<<endl;
	// }
	for(int x=1;x<=n;x+=sq)
	{
		for(int i=be[x];i<=ed[x];i++)
			dq[bl[x]].pb(a[i]),++cnt[bl[x]][a[i]];
	}
	// T();
}
int tmp[N];
void update(int l,int r)
{
	if(bl[l]==bl[r])
	{
		int b=bl[l];
		int x=dq[b][r-be[l]];
		dq[b].erase(dq[b].begin()+(r-be[l]));
		dq[b].insert(dq[b].begin()+(l-be[l]),x);
		return;
	}
	// cout<<"*****&"<<endl;
	dq[bl[l]].insert(dq[bl[l]].begin()+ (l-be[l]),dq[bl[r]][r-be[r]]);
	// cout<<"*****"<<endl;
	++cnt[bl[l]][dq[bl[r]][r-be[r]]];
	--cnt[bl[r]][dq[bl[r]][r-be[r]]];
	dq[bl[r]].erase(dq[bl[r]].begin()+(r-be[r]));
	// cout<<"*****"<<endl;
	for(int b=bl[l]+1;b<=bl[r];b++)
	{
		int t=dq[b-1].back();
		dq[b].push_front(t);
		++cnt[b][t];
		dq[b-1].pop_back();
		--cnt[b-1][t];
	}
}
int query(int l,int r,int k)
{
	int res=0;
	if(bl[l]==bl[r])
	{
		int  b=bl[l];
		for(int i=l;i<=r;i++)
			if(dq[b][i-be[l]]==k)res++;
		return res;
	}
	res+=query(l,ed[l],k);
	
	for(int b=bl[l]+1;b<=bl[r]-1;b++)
	{
		res+=cnt[b][k];
	}
	res+=query(be[r],r,k);
	return res;
}
int main()
{
	speed();
	// freopen("in.in","r",stdin);
	// freopen("fk.out","w",stdout);
	cin>>n;
	sq=max(3,(int)sqrt(n));
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
	}
	init();
	// cout<<"********"<<endl;
	cin>>q;
	int op,l=0,r=0,last=0,k;
	while(q--)
	{
		cin>>op>>l>>r;
		
		l=(l+last-1)%n+1;
		r=(r+last-1)%n+1;
		if(l>r)swap(l,r);
		if(op==1)
		{
			// cout<<"*****"<<endl;
			update(l,r);
			// cout<<"*****"<<endl;
		}
		else
		{
			cin>>k;
			k=(k+last-1)%n+1;
			last=query(l,r,k);
			cout<<last<<endl;
		}
	}
	return 0;
}

相關文章