牛客网暑期ACM多校训练营(第八场
B Filling pools
别问我为什么,google就完事了。
贴一个地址。
https://math.stackexchange.com/questions/2732802/computing-nth-schr%C3%B6der-number
#include<bits/stdc++.h>
using namespace std;
const int maxn=300000;
const int mod=998244353;
long long ans[maxn];
int inv[maxn];
void invTable(int n, int p, int inv[]) {
inv[1] = 1;
for(int i = 2; i <= n; ++i)
inv[i] = 1LL*(p-p/i) * inv[p%i] % p;
}
int main()
{
invTable(maxn-1,mod,inv);
int n;
scanf("%d",&n);
ans[0]=1;
ans[1]=2;
for(int i=2;i<=n;i++)
ans[i]=(((6*i-3)%mod*ans[i-1]%mod-(i-2)*ans[i-2]%mod)%mod+mod)%mod*inv[i+1]%mod;
printf("%lld\n",ans[n-1]);
}
E Touring cities
我们可以分类讨论一下,可以发现当n或者m是偶数的时候,转一圈就能回来了,时间即为n*m,而当n和m都为奇数时,最多要n*m+1,我们再想,最后一个点会是哪一些,如果最后一个点的有一条直接到(1,1)的路径,那么时间也可以为n*m了。我们画图又可以发现,如果把整个图的点按照黑白相间的方式染色((1,1)为黑色),那么最后一个点都是黑点。
一开始我就按照上面的方式写了,然而错了。。看了题解才发现其实如果黑色和黑色相连的话,那么时间就能为n*m了。。
#include<bits/stdc++.h>
using namespace std;
int mp[105][105];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
memset(mp,0,sizeof(mp));
int n,m,k;
scanf("%d %d %d",&n,&m,&k);
int x1,y1,x2,y2;
bool flag=0;
for(int i=1;i<=k;i++)
{
scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
if(x1!=x2||y1!=y2)
if((x1+y1)%2==0&&(x2+y2)%2==0)
flag=1;
}
if(n%2==0||m%2==0||flag)
printf("%d\n",n*m);
else printf("%d\n",n*m+1);
}
}
H Playing games
根据nim博弈的结论来看,我们实际上就是要找到最多的数,他们异或和为0.假设这n个数异或和为v,那么问题又可以进行转换,就是找出最少的数ans他们的异或和为v,那么答案就为n-ans
怎么找呢,这里有两点要提。
1,是ans至多也就19个,因为都不大于1<<19(感觉很有道理但不知道怎么证明)
2,FWT的数学含义需要知道。
我们这里就可以进行二分ans啦,然后再用FWT判断是否可以找到一种方案异或和为v。
#include<bits/stdc++.h>
using namespace std;
const int maxa=(1<<19);
const int mod=1e9+7;
int quick_mul(int a,int b,int mod)
{
int res=1;
while(b)
{
if(b%2)res=1LL*res*a%mod;
b/=2;
a=1LL*a*a%mod;
}
return res;
}
int a[maxa];
int b[maxa];
int inv2=5e8+4;
void FWT(int a[],int n,int flag){
for (int d=1;d<n;d<<=1)
for (int i=0;i<n;i+=(d<<1))
for (int j=0;j<d;j++){
int x=a[i+j],y=a[i+j+d];
a[i+j]=(x+y)%mod;
a[i+j+d]=(x-y)%mod;
if (flag==-1){
a[i+j]=1LL*a[i+j]*inv2%mod;
a[i+j+d]=1LL*a[i+j+d]*inv2%mod;
}
}
}
int v;
bool check(int k)
{
for(int i=0;i<maxa;i++)
b[i]=quick_mul(a[i],k,mod);
FWT(b,maxa,-1);
b[v]%=mod;
b[v]=(b[v]+mod)%mod;
if(b[v])return 1;
return 0;
}
int main()
{
int n;
scanf("%d",&n);
v=0;
int x;
for(int i=1;i<=n;i++)
{
scanf("%d",&x);
a[x]++;
v^=x;
}
if(v==0)
{
printf("%d\n",n);
return 0;
}
a[0]=1;
FWT(a,maxa,1);
int l=1,r=19;
int ans;
while(l<=r)
{
int mid=l+r>>1;
if(check(mid))
{
ans=mid;
r=mid-1;
}
else l=mid+1;
}
printf("%d\n",n-ans);
return 0;
}
这里还有一点要提,为了使得这个具有单调性,我们需要使a[0]>0,a代表的是下标为i出现的次数,根据fwt的数学含义看,我们要拿那个二分的次数时,需要把之前的结果也存起来,也就相当于有一次拿了0,所以我们必须使a[0]>0,才能使二分具有单调性。
下一篇: 牛客网暑期ACM多校训练营(第七场
推荐阅读
-
2019牛客暑期多校训练营(第二场)H Second Large Rectangle
-
2020牛客暑期多校训练营(第四场)——Basic Gcd Problem
-
2020牛客暑期多校训练营(第五场)
-
2020牛客暑期多校训练营(第九场) The Flee Plan of Groundhog
-
2020暑期牛客多校训练营第九场(K)The Flee Plan of Groundhog(lca,树形dp)
-
2020牛客暑期多校训练营(第二场)Cover the Tree
-
2020牛客暑期多校训练营(第一场)H-Minimum-cost Flow
-
2020牛客暑期多校 第一场 F Infinite String Comparision(字符串)
-
Harmony Pairs 2020牛客暑期多校训练营(第六场)
-
2020牛客暑期多校训练营(第五场)解题报告DEFI