前言

好像每个题目背景所描述的人都是某部番里的角色,热切好像都挺惨的(情感上的惨)。

然后我只知道 T1 的莓,确实挺惨。。。

T1 莓良心

解题思路

首先答案只与 \(w\) 的和有关系,于是问题就变成了对于一个点求出每一个所在组的大小以及对应的方案数。

考场上想的是枚举组的大小,然后预处理一下 \(n\) 个数字划分为 \(m\) 个非空集合的方案数。

一开始想的是隔板法,显然不对,然后就尝试 DP 计算,就有了 \(f_{i,j}=f_{i-1,j}\times j+f_{i-1,j-1}\)

一直想矩阵快速幂,看了半天才发现这 TM 两维,我优化个鬼!!

考完之后才知道这个是第二类斯特林数,然后才发现这玩意可以 NTT 暴算求出来一行或者一列的值,是我浅薄了。。。

官方题解的做法非常不一样,对于一对数 \(u,v\) 当两者被分到一个组中就会多出来 \(w_u+w_v\) 的贡献。

然后答案就是 \((\sum\limits_{i=1}^n w_i)\times(\;{n \brace k}+(n-1)\times {n-1 \brace k}\;)\)

发现可以直接容斥去求:

\[\displaystyle{n \brace k}=\frac{1}{k!}\sum_{i=0}^k(-1)^i \binom{k}{i}(k-i)^n
\]

然后 \(\mathcal{O}(n)\) 的线性筛或者 \(\mathcal{O}(nlogn)\) 的快速幂均可。

code

#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"RP++"<<endl
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=1e6+10,M=2e3+10,mod=998244353;
int n,m,ans,base,fac[N],ifac[N] ;
int power(int x,int y,int p=mod)
{
int temp=1;
while(y)
{
if(y&1) temp=temp*x%p;
x=x*x%p; y>>=1;
}
return temp;
}
int C(int x,int y){return fac[x]*ifac[y]%mod*ifac[x-y]%mod;}
int STL(int x,int y)
{
int temp=0;
for(int i=0,bas=1;i<=y;i++,bas=-bas) temp=(temp+bas*C(y,i)*power(y-i,x)%mod+mod)%mod;
return temp*ifac[y]%mod;
}
#undef int
int main()
{
#define int long long
freopen("ichigo.in","r",stdin); freopen("ichigo.out","w",stdout);
n=read(); m=read(); fac[0]=ifac[0]=1;
for(int i=1;i<=n;i++) base=(base+read())%mod,fac[i]=fac[i-1]*i%mod;
ifac[n]=power(fac[n],mod-2); for(int i=n-1;i>=1;i--) ifac[i]=ifac[i+1]*(i+1)%mod;
printf("%lld",base*(STL(n,m)%mod+STL(n-1,m)%mod*(n-1)%mod)%mod);
return 0;
}

T2 尽梨了

解题思路

比较直接的一个 DP 就是 \(f_{i,j}\) 前 \(i\) 个商店买 \(j\) 个物品的最短时间。

发现在 \(a_i\) 不为 0 时,增长是指数级别的,于是每次转移只要 \(log\) 次就够了。

然后就是对于 \(a_i\) 为 0 的情况进行处理了,直接维护一个前缀和二分即可。

代码实现上有一些小细节。

code

#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"RP++"<<endl
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=2e5+10;
int n,m,ans,pos,lim,f[N],pre[N];
struct Node{int a,b;}s[N];
bool comp(Node x,Node y){x.b++;y.b++;if(x.b*y.a!=y.b*x.a)return x.b*y.a<y.b*x.a;return x.b<y.b;}
#undef int
int main()
{
#define int long long
freopen("eriri.in","r",stdin); freopen("eriri.out","w",stdout);
n=read(); m=read(); lim=(int)log2(m)+1; memset(f,0x3f,sizeof(f));
for(int i=1;i<=n;i++) s[i].a=read(),s[i].b=read();
f[0]=0; sort(s+1,s+n+1,comp); pos=n+1;
for(int i=1;i<=n;i++) if(!s[i].a){pos=i;break;}
for(int i=1;i<=n;i++) s[i].b+=s[i].a+1,s[i].a++;
for(int i=pos;i<=n;i++) pre[i]=pre[i-1]+s[i].b;
for(int i=1;i<pos;i++)
for(int j=min(i,lim);j>=1;j--)
if(f[j-1]<=m) f[j]=min(f[j],f[j-1]*s[i].a+s[i].b);
for(int i=0;i<=min(n,lim);i++)
{
if(f[i]>m) continue;
int l=pos,r=n,temp=-1;
while(l<=r)
{
int mid=(l+r)>>1;
if(pre[mid]<=m-f[i]) temp=mid,l=mid+1;
else r=mid-1;
}
ans=max(ans,i+((~temp)?temp-pos+1:0));
}
printf("%lld",ans);
return 0;
}

T3 团不过

解题思路

很妙的一个题。

设 \(p(i)\) 表示 \(i\) 堆石子的方案数 \(p(i)=(2^n-1)^{\underline{i}}\) 。

设 \(f(n)\) 表示 \(n\) 堆石子先手必败的方案数,转移考虑在 \(i-1\) 堆石子后再添加一堆与 \(i-1\) 堆异或和相等的石子堆。

也就是 \(p(n-1)\) ,但是如果 \(i-1\) 堆石子异或和已经是 0 那么显然是不合法的,需要减去。

还有一种情况就是 \(i-2\) 堆石子的异或和为 0 新加入了两堆相同的石子,显然也是不可以的,也需要减去。

因此就有了:

\[f(i)=p(i-1)-f(i-1)-f(i-2)\times(i-1)\times(2^n-i+1)
\]

直接递推,然后拿总方案数减去就好了。

code

#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"RP++"<<endl
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=1e7+10,mod=1e9+7;
int n,p[N],p2[N],f[N];
#undef int
int main()
{
#define int long long
freopen("yui.in","r",stdin); freopen("yui.out","w",stdout);
n=read(); p2[0]=1; for(int i=1;i<=n;i++) p2[i]=p2[i-1]*2%mod;
p[0]=1; for(int i=1;i<=n;i++) p[i]=p[i-1]*(p2[n]-i)%mod;
for(int i=3;i<=n;i++) f[i]=(p[i-1]-f[i-1]-(i-1)*f[i-2]%mod*(p2[n]-i+1)%mod+2*mod)%mod;
printf("%lld",(p[n]-f[n]+mod)%mod);
return 0;
}

T4 七负我

解题思路

最优的策略就是我们把所有的值都平均分配到一个完全图中,可以用 调整法 来证明。

然后直接枚举是 \(2^n\) 的无法接受,考虑 \(meet\;in\;the\;middle\)

于是枚举前 \(\frac{n}{2}\) 里的完全图,然后看他对于后 \(\frac{n}{2}\) 个点的连边。

再预处理出后 \(\frac{n}{2}\) 个点所有点集的所包含的完全图的个数。

然后枚举前 \(\frac{n}{2}\) 个点的点集,然后看他们对于后 \(\frac{n}{2}\) 连边的并集合并即可。

代码里好像有一个细节错了,但是错的那个点小于20,我直接。。。组合拳??

code

#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"RP++"<<endl
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=50;
int n,m,m1,m2,all,maxn,e[N],f[1<<20];
#undef int
int main()
{
#define int long long
freopen("nanami.in","r",stdin); freopen("nanami.out","w",stdout);
n=read(); m=read(); all=read(); m1=n>>1; m2=n-m1; if(n<=20) m1=n;
for(int i=1,x,y;i<=m;i++) x=read(),y=read(),e[x]|=1ll<<y-1,e[y]|=1ll<<x-1;
for(int sta=1;sta<(1ll<<m1);sta++)
{
int sum=__builtin_popcount(sta); if(sum<=maxn) continue;
for(int i=1;i<=m1;i++) if((sta>>i-1)&1) if((e[i]&sta)!=(sta^(1ll<<i-1))) goto X;
maxn=max(maxn,sum);X:;
}
if(n<=20) printf("%.6lf",(1.0*(maxn*(maxn-1)/2))*(1.0*all)/(1.0*maxn)*(1.0*all)/(1.0*maxn)),exit(0);
for(int sta=1;sta<(1ll<<m2);sta++)
{
int sum=__builtin_popcount(sta);
for(int i=1;i<=m2;i++) if((sta>>i-1)&1) if(((e[i+m1]>>m1)&sta)!=(sta^(1ll<<i-1))) goto Y;
f[sta]=sta; maxn=max(maxn,sum); Y:;
}
for(int sta=0;sta<(1ll<<m2);sta++)
{
int U=(1ll<<m2)-1,sum=__builtin_popcount(sta);
for(int i=1;i<=m2;i++) if((sta>>i-1)&1) U&=e[i+m1]>>m1;
if(!U&&sum!=1) continue;
for(int i=1;i<=m2;i++)
if((((sta>>i-1)&1)^1))
if((((e[i+m1]>>m1)&sta)==sta&&(U&(1ll<<i-1)))){if(__builtin_popcount(f[sta|(1ll<<i-1)])<sum+1) f[sta|(1ll<<i-1)]=f[sta]|(1ll<<i-1);}
else if(__builtin_popcount(f[sta|(1ll<<i-1)])<sum) f[sta|(1ll<<i-1)]=f[sta];
}
for(int sta=1;sta<(1ll<<m1);sta++)
{
int U=(1<<m2)-1,sum=__builtin_popcount(sta);
for(int i=1;i<=m1;i++) if((sta>>i-1)&1) if((e[i]&sta)!=(sta^(1ll<<i-1))) goto Z;
for(int i=1;i<=m1;i++) if((sta>>i-1)&1) U&=e[i]>>m1;
maxn=max(maxn,sum+__builtin_popcount(f[U])); Z:;
}
printf("%.6lf",(1.0*(maxn*(maxn-1)/2))*(1.0*all)/(1.0*maxn)*(1.0*all)/(1.0*maxn));
return 0;
}

NOIP模拟85(多校18)的更多相关文章

  1. NOIP模拟83(多校16)

    前言 CSP之后第一次模拟赛,感觉考的一般. 不得不吐槽多校联测 OJ 上的评测机是真的慢... T1 树上的数 解题思路 感觉自己思维有些固化了,一看题目就感觉是线段树. 考完之后才想起来这玩意直接 ...

  2. Noip模拟80 2021.10.18

    预计得分:5 实际得分:140?????????????? T1 邻面合并 我考场上没切掉的大水题....(证明我旁边的cty切掉了,并觉得很水) 然而贪心拿了六十,离谱,成功做到上一篇博客说的有勇气 ...

  3. Noip模拟43 2021.8.18

    T1 地一体 可以树形$dp$,但考场没写出来,只打了没正确性的贪心水了$30$ 然后讲题的时候B哥讲了如何正确的贪心,喜出望外的学习了一下 不难发现 每次士兵都会直接冲到叶子节点 从深的点再返回到另 ...

  4. NOIP模拟92(多校25)

    前言 所以说这次是 HZOI 多校联测巅峰????(题目,数据过水??) T1 石子合并 解题思路 签到题. 发现我们可以给每个数字附一个正负号,每个数字的贡献就是它本身乘上这个符号. 发现至少应该有 ...

  5. NOIP模拟84(多校17)

    T1 宝藏 解题思路 考场上一眼出 \(nlog^2\) 做法,然后没看见是 1s 3e5 的数据,我竟然以为自己切了?? 考完之后尝试着把二分改为指针的移动,然后就过了??或许是数据水吧,感觉自己的 ...

  6. NOIP模拟86(多校19)

    T1 特殊字符串 解题思路 \(f_{i,j}\) 表示前 \(i\) 个字符中结尾为 \(j\) 的最大贡献. 转移枚举当前位置于之前位置结尾的组合加上贡献即可. 对于边界问题,容易发现选择 1 一 ...

  7. NOIP模拟88(多校21)

    前言 对于这套题的总体感觉就是难,然后就是自己很菜... 对于 T1 考试时只会一个最垃圾的背包,考完之后对于思路这一块也不是很顺利,大概这就是薄弱的地方吧. 然后 T2 是比较简单的一道题了,但是考 ...

  8. NOIP模拟96(多校29)

    T1 子集和 解题思路 大概是一个退背包的大白板,然而我考场上想复杂了,竟然还用到了组合数. 但是大概意思是一样的,有数的最小值一定是一个在 \(a\) 数组中存在的数字. 那么我们想办法除去它对应的 ...

  9. NOIP模拟99(多校31)

    T1 法阵 解题思路 原题3100,张口放 T1(出题人原话) 思维题,合法的情况其实就是上下两个梯形拼起来的样子. 他们的边界都是在 \(i\) 轴上面,但是不能相交. 于是我们可以尝试两者相交的纵 ...

随机推荐

  1. TypeScript 中命名空间与模块的理解?区别?

    一.模块 TypeScript 与ECMAScript 2015 一样,任何包含顶级 import 或者 export 的文件都被当成一个模块 相反地,如果一个文件不带有顶级的import或者expo ...

  2. 密码学系列之:bcrypt加密算法详解

    目录 简介 bcrypt的工作原理 bcrypt算法实现 bcrypt hash的结构 hash的历史 简介 今天要给大家介绍的一种加密算法叫做bcrypt, bcrypt是由Niels Provos ...

  3. EF架构封装类

    http://www.woxihuan.com/46528208/1323334777088641.shtml http://www.ediclot.com/archives/2368 http:// ...

  4. vue中的watch

    1.第一种 watch:{ total:{ // total:要检测的数据   handler:(val,oldVal)=>{ // handler方法自动执行   }, deep:true / ...

  5. DFS与DFS迷宫问题

    一天蒜头君掉进了一个迷宫里面,蒜头君想逃出去,可怜的蒜头君连迷宫是否有能逃出去的路都不知道. 看在蒜头君这么可怜的份上,就请聪明的你告诉蒜头君是否有可以逃出去的路. 输入格式 第一行输入两个整数n 和 ...

  6. 宝塔面板使用PM2命令提示Command Not Found解决方案

    1.查看node版本 进入/www/server/nvm/versions/node 查看node版本 2.复制以下代码 以node版本v12.18.1举例 PATH=$PATH:/www/serve ...

  7. js不记录某个url链接历史访问,返回时不返回该链接

    (function(){ var fnUrlReplace = function (eleLink) { if (!eleLink) { return; } var href = eleLink.hr ...

  8. python学习笔记(十五)-unittest单元测试的一个框架

    unittest 单元测试的一个框架什么框架 一堆工具的集合. TestCase TestSuite 测试套件,多个用例在一起 TestLoader是用来加载TestCase到TestSuite中的 ...

  9. turtle setup和screensize

    关于setup有明确的定义,它包括4个参数width,height,startx,starty, setup定义窗体的大小和相对位置,并隐含定义了画布的位置,缺省是居中占整个屏幕的一半[setup() ...

  10. 小白学习Python英语基础差怎么办,都帮你想好拉!看这里

    运算符与随机数 1.module:模块 2.sys(system):系统 3.path:路径 4.import:导入 5.from:从- 定义函数与设定参数 1.birthday:出生日期 2.yea ...