模拟7题解 T2

Posted casun547

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模拟7题解 T2相关的知识,希望对你有一定的参考价值。

T2 visit

[组合数学][中国剩余定理]

 

一场考试难得见两个数学题

本来想矩阵快速幂,显然空间复杂度不行,主要是没时间,就没打

 

正解:

首先推波式子

1.$C_t^k$    在t步中总共选出k步向上走,但最终只会走到m,到达m后,会又向下走k-m步,并会再向上走k-m步

2.$C_t-k^k-m$  在剩下的t-k步中选出向下走的k-m步

 3. 先介绍一个小技巧:eg  10 分成两个数,使两数之和为10,之差为4,

                 则大数(10+4)/2=7,小数(10-4)/2=3

 $C_t-2k+m^\fract-2k+m+n2$    此时还剩t-k-(k-m)=t-2k+m 步,这些用来分给向左和右的步数,因为最终要向右到n

              所以向右的总步数-向左的总步数=n,由以上技巧

                                t-2k+m是和,n是差,相加再/2是就是向右的步数

             在$t-2k+m$中选出向右的$\fract-2k+m+n2$步数

用向上,下,和左右的组合数相乘得到总步数

关键是k的范围:首先k>=m,否则上不去,

        同理向右的$\fract-2k+m+n2$>=n

        联立解得$k\in[m,\fract+m-n2]$

合起来:$\sum\limits_k=m^\fract+m-n2(C_t^k\times C_t-k^k-m\times C_t-2k+m^\fract-2k+m+n2)$

 

如何实现?

1.对于mod是质数的情况,直接 预处理+lucas定理

2.若mod是由若干个质数相乘得到,将mod分解质因数,

对于每个质因子q[i],原式对其取模得到的结果就是其余数,记做b[i]

那么问题就转化成了最终结果ans≡b[i](%p[i]) 在%mod情况下的线性同余方程组,用CRT求解即可

 

负数的情况变成正的来处理

技术图片
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<vector>
 5 #define int long long
 6 using namespace std;
 7 const int maxn=10000000;
 8 int t;
 9 vector<int>q;
10 int exgcd(int a,int b,int &x,int &y)
11 
12     if(!b)x=1,y=0;return a;
13     int d=exgcd(b,a%b,x,y);
14     int tmp=x;x=y;y=tmp-(a/b)*y;
15     return d;
16 
17 int b[maxn+5];
18 int crt(int mod)
19 
20     int ans=0;
21     for(int i=0;i<q.size();i++)
22     
23         int tmp=mod/q[i],x,y;
24         exgcd(tmp,q[i],x,y);
25         ans=(ans+tmp*x*b[i])%mod;
26     
27     return (ans%mod+mod)%mod;
28 
29 int inv[maxn+5],fac[maxn+5];
30 void init(int mod)
31 
32     fac[0]=fac[1]=1;
33     inv[0]=inv[1]=1;
34     for(int i=2;i<=t;i++)
35     
36         fac[i]=fac[i-1]*i%mod;
37         inv[i]=(mod-mod/i)*inv[mod%i]%mod;
38     
39     for(int i=2;i<=t;i++)
40         inv[i]=inv[i-1]*inv[i]%mod;
41 
42 int C(int n,int m,int mod)
43 
44     if(m>n)  return 0;
45     return fac[n]*inv[m]%mod*inv[n-m]%mod;
46 
47 int lucas(int n,int m,int mod)
48 
49     if(!m)    return 1;
50     return lucas(n/mod,m/mod,mod)*C(n%mod,m%mod,mod)%mod;
51 
52 void divide(int n)
53 
54     for(int i=2;i<=sqrt(n);i++)
55     
56         if(n%i)continue;
57         q.push_back(i);
58         n/=i;
59     
60     if(n>1)q.push_back(n);
61 
62 signed main() 
63 
64     int ans=0,n,m,mod;
65     scanf("%lld%lld%lld%lld",&t,&mod,&n,&m);
66     if(n<0)n=-n;
67     if(m<0)m=-m;
68     divide(mod);
69     int st=m,en=(t+m-n)>>1;
70     if(q.size()==1)
71     
72         init(mod);
73         for(int k=st;k<=en;k++)
74             ans=(ans+lucas(t,k,mod)*lucas(t-k,k-m,mod)%mod*lucas(t-2*k+m,(t-2*k+m+n)>>1,mod)%mod)%mod;
75         printf("%lld\n",ans);
76         return 0;
77     
78     for(int i=0;i<q.size();i++)
79     
80         init(q[i]);
81         for(int k=st;k<=en;k++)
82             b[i]=(b[i]+lucas(t,k,q[i])*lucas(t-k,k-m,q[i])%q[i]*lucas(t-2*k+m,(t-2*k+m+n)>>1,q[i])%q[i])%q[i];
83     
84     printf("%lld\n",crt(mod));
85 
View Code

 

以上是关于模拟7题解 T2的主要内容,如果未能解决你的问题,请参考以下文章

2021.7.12提高B组模拟1T2 最短路径(DP)

题解——Codeforces Round #507 (based on Olympiad of Metropolises) T2(模拟)

$CSP$ $2019$ $Day2$ 模拟考试 题解报告

$NOIP 2016 Day1$ 模拟考试 题解报告

$NOIP 2018 Day2$ 模拟考试 题解报告

省选模拟五十六 题解