数论三之排列组合Ⅱ——Virus Tree 2,RGB Coloring,123 Triangle,排列计数,排队,卡农

丝且人一口

  • Virus Tree 2
    • description
    • solution
    • code
  • RGB Coloring
    • description
    • solution
    • code
  • 123 Triangle
    • description
    • solution
    • code
  • [SDOI2016]排列计数
    • description
    • solution
    • code
  • [HNOI2012]排队
    • description
    • solution
    • code
  • [HNOI2011]卡农
    • description
    • solution
    • code

Virus Tree 2

description

solution

距离不超过222的点,可能是儿子/孙子/父亲/爷爷

考虑从上到下,由上面的颜色选取决定下面的颜色

显然,第一个点有KKK种选择,第二个点有K−1K-1K1种,每次不同都要−1-11

答案就是每个点的选择的乘积

所以只需要把这种过程的递减通过dfs树来实现

对于现在的子树根节点uuu,如果vvv是第一个儿子,那么需要考虑vvv有没有爷爷

如果不是第一个儿子,那么就是前一个儿子的方案数再−1-11

code

#include <cstdio>
#include <vector>
using namespace std;
#define mod 1000000007
#define int long long
#define maxn 1000005
vector < int > G[maxn];
int n, k;
int w[maxn];void dfs( int u, int fa ) {int r = 0;for( auto v : G[u] ) {if( v == fa ) continue;else {if( r ) w[v] = r - 1;else if( ! fa ) w[v] = k - 1;else w[v] = k - 2;r = w[v]; }}for( auto v : G[u] ) if( v ^ fa ) dfs( v, u );
}signed main() {scanf( "%lld %lld", &n, &k );for( int i = 1, u, v;i < n;i ++ ) {scanf( "%lld %lld", &u, &v );G[u].push_back( v );G[v].push_back( u );}w[1] = k;dfs( 1, 0 );int ans = 1;for( int i = 1;i <= n;i ++ )if( w[i] <= 0 ) return ! printf( "0\n" );else ans = ans * w[i] % mod;printf( "%lld\n", ans );return 0;
}

RGB Coloring

description

solution

将绿色A+BA+BA+B看成既涂了红色AAA,又涂了蓝色BBB,则红色和蓝色格子彼此独立,就算涂在同一个格子上也没关系

枚举红色格子的数量iii,计算得出蓝色格子数量j=K−A×iBj=\frac{K-A\times i}{B}j=BKA×i

判断格子数量为整数且都在nnn以内即可,然后用组合计数从nnn个格子中选红/蓝色

∑Cni×Cnj\sum C_n^i\times C_n^jCni×Cnj

code

#include <cstdio>
#define int long long
#define mod 998244353
#define maxn 300005
int n, A, B, k;
int fac[maxn], inv[maxn];int qkpow( int x, int y ) {int ans = 1;while( y ) {if( y & 1 ) ans = ans * x % mod;x = x * x % mod;y >>= 1;}return ans;
}void init() {fac[0] = inv[0] = 1;for( int i = 1;i <= n;i ++ )fac[i] = fac[i - 1] * i % mod;inv[n] = qkpow( fac[n], mod - 2 );for( int i = n - 1;i;i -- )inv[i] = inv[i + 1] * ( i + 1 ) % mod;
}int C( int n, int m ) {if( m < 0 || n < m ) return 0;else return fac[n] * inv[m] % mod * inv[n - m] % mod;
}signed main() {scanf( "%lld %lld %lld %lld", &n, &A, &B, &k );init();int ans = 0; for( int i = 0, j;i <= n;i ++ ) {if( ( k - A * i ) % B ) continue;else j = ( k - A * i ) / B;ans = ( ans + C( n, i ) * C( n, j ) ) % mod;}printf( "%lld\n", ans );return 0;
}

123 Triangle

description

solution

N>1N>1N>1式子是差分形式,后面序列只有能是0/1/20/1/20/1/2

(除非N=1N=1N=1的情况答案有可能是333

如果此时序列有111,那么答案一定只能是0/10/10/1,因为0/20/20/2碰到111都会变成111

如果序列没有111,则答案只会是0/20/20/2,对于这种情况,将每个数/2/2/2得到结果后再×2\times 2×2是等价的

所以现在的答案都只会是0/10/10/1,考虑在(mod2)\pmod 2(mod2)意义下做

(mod2)\pmod 2(mod2)的情况下,加减法可以看成二进制的异或

所求即为一段序列相邻两个数异或直到最后成一个数的答案

考虑每个数被异或的次数,这其实是个倒杨辉三角(0,0)(0,0)(0,0)开始

长为nnn的序列的第iii个元素被异或的次数为Cn−1i−1C_{n-1}^{i-1}Cn1i1

计算在模222意义下(除法不一定有逆元)的组合数

  • 计算每个阶乘中分解222的次数,将除法变成减法,对于组合数最后剩下的222的次数为000,则为1(mod2)1\pmod 21(mod2),反之0(mod2)0\pmod 20(mod2)
  • 阶乘的分解,拆分成对每个数求出分解中222的次数,做前缀和

code

#include <cmath>
#include <cstdio>
#define maxn 1000005
int n;
char s[maxn];
int x[maxn], cnt[maxn]; int main() {scanf( "%d %s", &n, s + 1 );n --;for( int i = 1;i <= n;i ++ )x[i] = fabs( s[i] - s[i + 1] );bool flag = 1;for( int i = 1;i <= n;i ++ )if( x[i] == 1 ) { flag = 0; break; }if( flag ) for( int i = 1;i <= n;i ++ )x[i] >>= 1;for( int i = 1;i <= n;i ++ ) {int t = i;while( ! ( t & 1 ) ) t >>= 1, cnt[i] ++;cnt[i] += cnt[i - 1];}int ans = 0;for( int i = 1;i <= n;i ++ )ans ^= cnt[n - 1] - cnt[i - 1] - cnt[n - i] ? 0 : ( x[i] & 1 );if( flag ) ans <<= 1;printf( "%d", ans );return 0;
} 

[SDOI2016]排列计数

description

solution

组合数从nnn个中选mmm个强制ai=ia_i=iai=i,剩下的n−mn-mnmai≠ia_i≠iai=i,就是n−mn-mnm的错排数

code

#include <cstdio>
#define mod 1000000007
#define int long long
#define maxn 1000005
int fac[maxn], inv[maxn], D[maxn];
int T, n, m;int qkpow( int x, int y ) {int ans = 1;while( y ) {if( y & 1 ) ans = ans * x % mod;x = x * x % mod;y >>= 1;}return ans;
}void init() {fac[0] = inv[0] = 1;for( int i = 1;i < maxn;i ++ )fac[i] = fac[i - 1] * i % mod;inv[maxn - 1] = qkpow( fac[maxn - 1], mod - 2 );for( int i = maxn - 2;i;i -- )inv[i] = inv[i + 1] * ( i + 1 ) % mod;D[0] = 0, D[1] = 0, D[2] = 1;for( int i = 3;i < maxn;i ++ )D[i] = ( D[i - 1] + D[i - 2] ) * ( i - 1 ) % mod;
}int C( int n, int m ) {return fac[n] * inv[m] % mod * inv[n - m] % mod;
}signed main() {init();scanf( "%lld", &T );while( T -- ) {scanf( "%lld %lld", &n, &m );if( n == m ) printf( "1\n" ); else printf( "%lld\n", C( n, m ) * D[n - m] % mod );}return 0;
}

[HNOI2012]排队

description

solution

不给模数还明示答案可能很大,赤裸裸的大整数胁迫!!居心叵测!!

两名老师真的是很烦了,没有这么讨人厌的老师,可以直接女生插板法了

  • 两名老师之间是男生

    先排男生AnnA_n^nAnn,产生n+1n+1n+1个空

    再插板两名老师,An+12A_{n+1}^2An+12,产生n+3n+3n+3个空

    最后插板mmm名女生,An+3mA_{n+3}^mAn+3m

  • 两名老师之间是女生

    先排男生AnnA_n^nAnn

    再打包两名老师放同一个隔板里,老师间还有顺序,A22Cn+11A_2^2C_{n+1}^1A22Cn+11

    先强制选一名女生放进老师中间mmm,剩下的就隔板插

    男生nnn个,老师和强制女生打包装成一个,总共是n+1n+1n+1个,产生n+2n+2n+2个空,An+2m−1A_{n+2}^{m-1}An+2m1

综上,ans=AnnAn+12An+3m+A22Cn+11An+2m−1ans=A_n^nA_{n+1}^2A_{n+3}^m+A_2^2C_{n+1}^1A_{n+2}^{m-1}ans=AnnAn+12An+3m+A22Cn+11An+2m1

同样,老师不相邻===不考虑老师−-老师相邻

  • 不考虑老师

    把老师当成男的,女的直接插,An+2n+2An+3mA_{n+2}^{n+2}A_{n+3}^mAn+2n+2An+3m

  • 老师相邻

    捆绑法强制两名老师一起当成一个男的A22An+1n+1An+2mA_2^2A_{n+1}^{n+1}A_{n+2}^mA22An+1n+1An+2m

二者做差就是答案
在这里插入图片描述

code

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int n, m;struct Int {int g[20000], len;Int() {memset( g, 0, sizeof( g ) );len = 0;}Int( int x ) {memset( g, 0, sizeof( g ) );len = 0;if( ! x ) len = 1;else while( x ) g[len ++] = x % 10, x /= 10;}void clean() {while( len > 1 && ! g[len - 1] ) len --;}Int operator - ( Int t ) {Int ans;ans.len = len;for( int i = 0;i < t.len;i ++ ) {ans.g[i] = g[i] - t.g[i];if( ans.g[i] < 0 ) ans.g[i] += 10, g[i + 1] --;}for( int i = t.len;i < len;i ++ )ans.g[i] = g[i]; ans.clean();return ans;}Int operator * ( Int t ) {Int ans;ans.len = len + t.len;for( int i = 0;i < len;i ++ )for( int j = 0;j < t.len;j ++ )ans.g[i + j] += g[i] * t.g[j];for( int i = 0;i < ans.len;i ++ )ans.g[i + 1] += ans.g[i] / 10, ans.g[i] %= 10;ans.len ++;ans.clean();return ans;} void print() {for( int i = len - 1;~ i;i -- )printf( "%d", g[i] );}};Int calc( int n, int m ) {Int ans = ( 1 );for( int i = n - m + 1;i <= n;i ++ )ans = ans * i;return ans;
}int main() {scanf( "%d %d", &n, &m );Int ans;ans = calc( n + 2, n + 2 ) * calc( n + 3, m ) - calc( 2, 2 ) * calc( n + 1, n + 1 ) * calc( n + 2, m );	ans.print();return 0;
}

[HNOI2011]卡农

description

solution

同种音乐其实通过除以m!m!m!就可以消掉

相当于在SSS中选mmm个子集,满足

  • 子集非空
  • 不存在两个完全一样的子集
  • ∀i,i∈[1,n]\forall_{i,i\in[1,n]}i,i[1,n]每个元素出现次数为偶数

fi:f_i:fi: 考虑iii个子集,满足以上所有性质的方案数

  • 如果知道i−1i-1i1个子集的,那么iii个子集的集合就被确定了下来A2n−1i−1A_{2^n-1}^{i-1}A2n1i1
  • 如果子集是空,那么去掉这个子集剩下的i−1i-1i1个子集是合法方案fi−1f_{i-1}fi1
  • 如果iii子集与jjj子集重复,jjji−1i-1i1种选择,剔除这两个子集剩下i−2i-2i2子集是合法的fi−2f_{i-2}fi2iii子集选择有2n−1−(i−2)2^n-1-(i-2)2n1(i2)(排除掉剩下i−2i-2i2个子集,不能与之重复)

在这里插入图片描述

最后别忘了m!m!m!

code

#include <cstdio>
#define mod 100000007
#define int long long
#define maxn 1000005
int n, m;
int A[maxn], f[maxn];int qkpow( int x, int y ) {int ans = 1;while( y ) {if( y & 1 ) ans = ans * x % mod;x = x * x % mod;y >>= 1;}return ans;
}signed main() {scanf( "%lld %lld", &n, &m );f[0] = 1, f[1] = 0;int t = ( qkpow( 2, n ) - 1 + mod ) % mod;A[0] = 1;for( int i = 1;i <= m;i ++ )A[i] = ( A[i - 1] * ( t - i + 1 ) % mod + mod ) % mod;int MS = 1;for( int i = 2;i <= m;i ++ ) {f[i] = ( A[i - 1] - f[i - 1] - f[i - 2] * ( i - 1 ) % mod * ( t - i + 2 ) % mod ) % mod;MS = MS * i % mod;}printf( "%lld\n", ( f[m] + mod ) % mod * qkpow( MS, mod - 2 ) % mod );return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/317309.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

B - Labyrinth Gym - 102798B

B - Labyrinth Gym - 102798B 题意&#xff1a; n * m的地图&#xff0c;有k个障碍物&#xff0c;给你起点到终点&#xff0c;从起点到终点的最短距离 1<n,m<200000 nm<200000 0<k<42 1<q<100000 题解&#xff1a; 如果没有障碍物&#xff0c;两点之间…

P2483-[模板]k短路/[SDOI2010]魔法猪学院【主席树,堆】

正题 题目链接:https://www.luogu.com.cn/problem/P2483 题目大意 给出一个nnn个点mmm条边的一张带权有向图&#xff0c;求一个最大的kkk使得1∼n1\sim n1∼n的前kkk短路径长度和不超过EEE。 2≤n≤5000,1≤m≤2105,1≤E≤1072\leq n\leq 5000,1\leq m\leq 2\times 10^5,1\le…

.NET Core开发日志——OData

简述OData&#xff0c;即Open Data Protocol&#xff0c;是由微软在2007年推出的一款开放协议&#xff0c;旨在通过简单、标准的方式创建和使用查询式及交互式RESTful API。类库在.NET Core中想要使用OData功能的话需要添加Microsoft.AspNetCore.OData包。dotnet add package M…

数论四之综合训练——Magic Pairs,Crime Management,Top Secret,组合数问题

数论综合训练Magic PairsproblemsolutioncodeCF107D Crime ManagementproblemsolutioncodeUVA12183 Top SecretproblemsolutioncodeP3746 [六省联考2017]组合数问题problemsolutioncodeMagic Pairs problem 已知A0xB0y≡0(modn)A_0xB_0y\equiv 0\pmod nA0​xB0​y≡0(modn)恒…

P6776-[NOI2020]超现实树

正题 题目链接:https://www.luogu.com.cn/problem/P6776 题目大意 定义一次操作为将一棵树的叶子换成另一棵树。 定义一棵树TTT的grow(T)grow(T)grow(T)表示所有树TTT能够通过操作变成的树的集合。 现在给出mmm棵树TiT_iTi​&#xff0c;定义SSS为所有grow(Ti)grow(T_i)grow…

CodeForces:749(div1)750(div2)

文章目录前言CF450A Jzzhu and ChildrenDescription\text{Description}DescriptionSolution\text{Solution}SolutionCode\text{Code}CodeCF450B Jzzhu and SequencesDescription\text{Description}DescriptionSolution\text{Solution}SolutionCode\text{Code}CodeCF449A Jzzhu …

Steins;Game Gym - 102798J(未解决)

Steins;Game Gym - 102798J 题意&#xff1a; 给定n堆石子a&#xff0c;每堆石子被染成了黑色或者白色&#xff0c;现在两个人轮流进行以下的其中一个操作&#xff1a; 1、从石子数量最少的一个黑色石堆中拿走若干石子 2、从任意一个白色石堆中拿走若干石子 两个人都采取最优…

ML.NET 0.10特性简介

IDataView被单独作为一个类库包IDataView组件为表格式数据提供了非常高效的处理方式&#xff0c;尤其是用于机器学习和高级分析应用。它被设计为可以高效地处理高维数据和大型数据集。并且也适合处理属于更大的分布式数据集中的单个数据区块结点。在ML.NET 0.10中&#xff0c;I…

模板:模拟退火

文章目录前言解析流程示例代码trick所谓模拟退火&#xff0c;就是通过代码模拟退火 &#xff08;逃&#xff09; 前言 终于学了这个神奇的骗分算法 几次在大赛中都发现这算法是真的有学的必要 FFC可能真的要想想自己的题目对OI界的导向作用了 但学完以后还是感觉挺有意思的&a…

讨“动态规划“檄

我一直遵循着人不犯我我不犯人的原则&#xff0c;但是鉴于动态规划(dp)三番两次的挑衅&#xff0c;我忍无可忍决定发起反击&#xff0c;特写本文记录一下。 (本文整理一下以前做过的dp问题&#xff0c;并且把之前囤的大量dp都做做) acwing提高组 第一章 动态规划 背包模型题目集…

数论五之容斥——硬币购物,Gerald and Giant Chess,幸运数字,Sky Full of Stars,已经没有什么好害怕的了

容斥的神[HAOI2008]硬币购物problemsolutioncodeCF559C Gerald and Giant Chessproblemsolutioncode[SCOI2010]幸运数字problemsolutioncodeCF997C Sky Full of Starsproblemsolutioncode已经没有什么好害怕的了problemsolutioncode[JLOI2015]骗我呢problemsolutioncode容斥要么…

P4769-[NOI2018]冒泡排序【组合数学,树状数组】

正题 题目链接:https://www.luogu.com.cn/problem/P4769 题目大意 有一个冒泡排序的算法 输入&#xff1a;一个长度为 n 的排列 p[1...n] 输出&#xff1a;p 排序后的结果。 for i 1 to n dofor j 1 to n - 1 doif(p[j] > p[j 1])交换 p[j] 与 p[j 1] 的值然后给出一…

NET Core微服务之路:基于Ocelot的API网关Relay实现--RPC篇

前言我们都知道&#xff0c;API网关是工作在应用层上网关程序&#xff0c;为何要这样设计呢&#xff0c;而不是将网关程序直接工作在传输层、或者网络层等等更底层的环境呢&#xff1f;让我们先来简单的了解一下TCP/IP的五层模型。&#xff08;图片出自http://www.cnblogs.com/…

模板:长链剖分

所谓长链剖分&#xff0c;就是对长链进行剖分 &#xff08;逃&#xff09; 前言 很优雅的算法 利用对指针进行魔法操作将 n2n^2n2 的 dp 优化成线性 线性啊&#xff01;&#xff01;&#xff01; 解析 CF1009F Dominant Indices 给定一棵以 111 为根&#xff0c;nnn 个节点…

acwing 327. 玉米田

327. 玉米田 题意&#xff1a; m * n的土地&#xff0c;有的土地不育&#xff0c;有的可以种植&#xff0c;要求相邻的土地不能同时种植玉米&#xff0c;问有多少种种植方式 题解&#xff1a; 状压dp&#xff0c;先存每一行可能的状态&#xff0c;然后状态转移&#xff0c;…

Windows 10《描图》应用现已开源

点击上方蓝字关注“汪宇杰博客”《描图》是我最早的Windows 10应用&#xff0c;发布至今已3年多&#xff0c;积累了全球数百万用户&#xff0c;广受好评。现已开源。这款应用为不少小朋友带去了欢乐&#xff0c;体验绘画的乐趣&#xff0c;也帮助过专业用户复刻数百幅古代绘画。…

数论六之计算几何干货——计算几何模板解释全集 及 模板检验训练场

文章目录点和向量及运算直线和线段求解点到直线的距离/点在直线上求解点到线段的距离/点在线段上求解两条线段是否相交求解两直线的交点多边形求解多边形面积求解多边形重心求解判断定点与多边形的位置关系凸包graham扫描法graham扫描法加强版圆求解圆与直线的交点求解圆与圆的…

P7740-[NOI2021]机器人游戏【dp,bitset】

正题 题目链接:https://www.luogu.com.cn/problem/P7740 题目描述 题目大意摸了 小 R 有 mmm&#xff08;1≤m≤10001 \le m \le 10001≤m≤1000&#xff09;个机器人和 mmm 张纸带&#xff0c;第 iii&#xff08;1≤i≤m1 \le i \le m1≤i≤m&#xff09;个机器人负责对第 …

CodeForces:54

文章目录前言CF54A PresentsDescription\text{Description}DescriptionSolution\text{Solution}SolutionCF54B Cutting Jigsaw PuzzleDescription\text{Description}DescriptionSolution\text{Solution}SolutionCode\text{Code}CodeCF54C First Digit LawDescription\text{Desc…

[NOIP2016 提高组] 愤怒的小鸟

[NOIP2016 提高组] 愤怒的小鸟 题意&#xff1a; 有n只猪&#xff0c;给出猪的坐标(xi,yi),问最少用几个形如 yax^2bx 的曲线可以保证所有猪在曲线上&#xff0c;满足a<0,a,b为实数 n<18, 题解&#xff1a; 两个方法&#xff1a;爆搜或者状压dp 状压dp 看n<18也…