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\) 个红色(或蓝色),转移容易。