noip模拟19

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)

posted @ 2024-11-23 17:46  ccjjxx  阅读(14)  评论(0编辑  收藏  举报