noip模擬19

ccjjxx發表於2024-11-23

A 鏡的綺想 (mirror)

籤籤籤。

配對的點對一定 \(x\) 相同,那用 \(O(nm)\) 地匹配一下,因為有幾個點的 \(x\) 全都相同,所以 \(map\)\(umap\) 會塞到 \(n\times m\) 個數,顯然會爆炸,只能開桶,手動把縱座標搞成全正的,就行。

點選檢視程式碼
#include<bits/stdc++.h>
using namespace std;
int n,m;
const int N=5e3+3,M=4e6+6;
struct node{
	int x,y;
	int now;
}a[N],c[N];
int b[N<<1];
int cnt;
int mp[M];
int add=1e6;
signed main()
{
	freopen("mirror.in","r",stdin);
	freopen("mirror.out","w",stdout);
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0); 
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i].x>>a[i].y;
		a[i].y+=add;
	}
	for(int i=1;i<=m;i++)
	{
		cin>>c[i].x>>c[i].y;
		c[i].y+=add;
	}
	int ans=0;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			if(a[i].x==c[j].x)
			{
				mp[(a[i].y+c[j].y)]++;
				ans=max(ans,mp[(a[i].y+c[j].y)]);
			}
		}
	}
	cout<<ans;
}

B 萬物有靈 (animism)

貪心的考慮,從最底層往上走一定是最大的,然後發現,每一個 \(k\) 層的節點數之和是上一層的 \(\prod a_i\) 倍,因為 \(k\) 是奇數的情況會每層選的不同,於是可以果斷把 \(k\)\(2\),就是偶數了。

然後發現每一個整段是等比數列,用 \(\log\) 複雜度的求和方式算就行了,因為模數有可能是合數,不能算逆元。

點選檢視程式碼
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,k,mod;
const int N=1e6+5;
int a[N],sum[N],ans;
int ppow(int a,int b)
{
	int res=1;
	while(b)
	{
		if(b&1) res=(res*a)%mod;
		a=(a*a)%mod,b>>=1;
	}return res;
}
int f(int now,int d)
{
	if(d==1) return now;
	if(d==0) return 1;
	if(d%2==0) return (f(now,d/2)*(1+ppow(now,d/2))%mod)%mod;
	else return (ppow(now,d)+(((1+ppow(now,(d-1)/2))%mod)%mod*f(now,(d-1)/2)%mod)%mod)%mod;
}
signed main()
{
	freopen("animism.in","r",stdin);
	freopen("animism.out","w",stdout); 
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	cin>>n>>k>>mod;
	for(int i=0;i<k;i++) cin>>a[i];
	if(n<N)
	{
		sum[0]=1;
		for(int i=0;i<n;i++) sum[i+1]=sum[i]*a[i%k]%mod;
		for(int i=n;i>=0;i-=2) ans=(ans+sum[i])%mod;
		return cout<<ans,0;
	}
	sum[0]=1;
	for(int i=1;i<=k*2;i++) sum[i]=(sum[i-1]*a[(i-1)%k])%mod;
	if(n<=k*2)
	{
		for(int i=n;i>=0;i-=2) ans=(ans+sum[i])%mod;
		return cout<<ans,0;
	}
	int rd=n/(k*2);
	int S=sum[k*2];
	if(n%2==1)
	{
		int res=0;
		for(int i=1;i<=k*2;i+=2) res=(res+sum[i])%mod;
		int ret=f(S,rd-1)%mod;ret++;
		ans=(ans+res*ret%mod)%mod;
		int pp=ppow(S,rd);
		for(int i=n%(k*2);i>=1;i-=2) ans=(ans+sum[i]*pp%mod)%mod;
		ans=(ans%mod+mod)%mod;
		cout<<ans;
	}
	else
	{
		int res=0;
		for(int i=2;i<=k*2;i+=2) res=(res+sum[i])%mod;
		int ret=f(S,rd-1)%mod;ret++;
		ans=(ans+res*ret%mod)%mod;
		int pp=ppow(S,rd);
		for(int i=n%(k*2);i>=1;i-=2) ans=(ans+sum[i]*pp%mod)%mod;
		++ans;
		ans=(ans%mod+mod)%mod;
		cout<<ans;
	}
}

C 白石溪 (creek)

\(n^2\) 的 dp 是簡單的。設 dp_{i,j}$ 表示考慮到 \(i\) 位置,前面有 \(j\) 個紅色(或藍色),轉移容易。

D 上山崗 (uphill)