http://jzoj.net/senior/#contest/show/2848/0
http://jzoj.net/senior/#contest/show/2848/1
http://jzoj.net/senior/#contest/show/2848/2
昨天论坛:
我:
话说同学们要积极地打今天的T2,争取AC,这可是明天的T3
然后……
接着今天就爽死了o(╥﹏╥)o
看到题目的名字时,我想:“今天的题目真有意思,T2普及组绝对是送分的。”
一看T1,矩阵乘法?不对,n矩阵乘法不了。于是想了一个nk的DP,发现只能过30分,还不如打暴力。
再看T2,WTF?又是计数题?我的心态顿时就爆炸了
还好,我的心理承受能力还是有的,于是我转向T3——
又是计数题!今天真的要爽死了!
我昨天真的把出题人给激怒了吗?
但是很快,也才10分钟嘛我的心态就恢复了。
话说,今天的数据还是挺良心的嘛!T2给出那么多个x绝对有什么含义。
接着我就发现了x=1的规律: a n s n = 2 ( n − 1 ) 2 ans_n=2^{(n-1)^2} ansn=2(n−1)2
然后x是质数的情况也很快解决了: a n s n = 2 ( n − 1 ) 2 n ! ans_n=2^{(n-1)^2}n! ansn=2(n−1)2n!
但是x是和数的情况我没有弄出来。
最后暴力处理x=12和x=30的情况,结果前者的表20分钟打出来了,后者的表到比赛结束也没有弄出来。
最后T1暴力0分(TLE了?)+T2找规律&打表20分+T3人口普查分(暴力居然改不出来)=23分,rank 71。
被众大佬暴踩了。。。
苏DL居然考场切了?太强了%%%
可以把每一个 a i a_i ai化成 p i ⋅ m + q i p_i\cdot m+q_i pi⋅m+qi的形式,然后
∑ a i = ∑ ( p i ⋅ m + q i ) = ∑ p i ⋅ m + ∑ q i \begin{aligned} \sum a_i&=\sum(p_i\cdot m+q_i)\\[2ex] &=\sum p_i\cdot m+\sum q_i \end{aligned} ∑ai=∑(pi⋅m+qi)=∑pi⋅m+∑qi
设 s u m q = ∑ q i sumq=\sum q_i sumq=∑qi,显然 s u m q < k ⋅ m sumq<k\cdot m sumq<k⋅m且 s u m q ≡ n ( m o d    m ) sumq\equiv n\quad(\mod m) sumq≡n(modm),因此 s u m q sumq sumq只有k种取值,枚举一下,容斥求答案就可以了。
至于 ∑ p i ⋅ m \sum p_i\cdot m ∑pi⋅m这坨东西,显然有 ∑ p i = n − s u m q m \sum p_i=\cfrac{n-sumq}{m} ∑pi=mn−sumq,这就转化成了隔板问题,也很好处理。
最后把答案乘起来就可以了。
YMQ大佬比赛时找到了神奇的规律:
第一条规律暴力做就可以了。
第二条就是观察样例3,先把每一项除去正负数的情况,得到
n | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|
num | 1 | 3 | 21 | 282 | 6210 |
发现第 i 项貌似是第 i-1 项× i 2 i^2 i2,于是相减,得
n | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|
i 2 − n u m i − 1 i^2-num_{i-1} i2−numi−1 | - | 1 | 6 | 54 | 840 |
然后发现第 i 项剩余的数是第 i-2 项的倍数诶!
结论就得出了。
看到这些,你是否与我有同感:
YMQ大佬太强了!找规律这种东西,真不是我们正常人能做的。
或许可以学习吕乐大佬,用电脑暴力枚举方程式的各项系数。
指数里可能有二。
又因为指数可能有2,因此可能的系数有1,2,3,6,1/2,1/3,1/6等。
然后也不一定时i的某次方,可能涉及i-1或更多。
然而我试到:“f[i]与f[i-1],f[i-2]有关” 时已经搞定了。
f [ i ] = a ∗ i b ∗ ( i − 1 ) c ∗ f [ i − 1 ] + d ∗ i e ∗ ( i − 1 ) f ∗ f [ i − 2 ] ; f[i]=a*i^b*(i-1)^c*f[i-1]+d*i^e*(i-1)^f*f[i-2]; f[i]=a∗ib∗(i−1)c∗f[i−1]+d∗ie∗(i−1)f∗f[i−2];
暴力枚举abcdef,暴力尝试乘除,正负。
最后发现
a=1;
b=2;
c=0;
d=-0.5;
e=1;
f=2;
花式碾压正解。
由于质因数分解可能会T飞,x又已经给出了,这不就是出题人提示我们要打表吗?
然后我就打了表了。。。
注意:这里的表指的不是答案,而是各个数有多少个指数为1的质因子,多少个指数为2的质因子。
结果发现CJY没打表比我快了500ms+
TM的害我打了30分钟的表!
由于这题要求最长下降子序列的长度小于等于2,因此可以转变为求2个最长不下降子序列。
考虑求前缀最大值,显然第一个序列中的每一个数的前缀都比前一个数的要大,而对于剩余的数也有合法的排列。
因此问题就可以转变成在一个n*n格子图中,求(1,1)到(n,n)的合法路径个数。
可以分类讨论一下:
题解是这样说的:
分情况讨论:
- y ≥ x,那么该点一定在前缀max上。考虑反证,若其没有对前缀max产生贡献,那么x前面一定有一个大于y的数,同时x后面没有小于y的数,否则存在长度为3的下降子序列,也就是所有小于y 的数都在x之前,那么至少需要1 + y − 1 = y个位置,而y ≥ x > x − 1,x前面的位置不够,矛盾
- y < x,那么该点一定不对前缀max产生贡献。这是显然的
- 对于y < x的情况,考虑A的逆置换 A − 1 [ A i ] A^{−1}[A_i] A−1[Ai] = i,可以转换成另一 种情况,也就是说只要考虑y ≥ x的情况
- 那么什么路径是不合法的呢?由于我们求的是前缀最大值,且元素两两不相等,因此凡是触碰到直线y=x-1的路径都是不合法的。
不合法的A→B的路径必定是经过直线y=x-1的,我们把与直线相交后的路径关于直线对称,如下图所示:
蓝色的即为对称后的路径,这样就能方便处理不合法的方案了。
最后答案显然是 (1,1)→(x,y)的合法+(x,y)→(n,n)的合法方案。(如果x>y就要交换x,y)
但是我发现我太菜了,连(x1,y1)→(x2,y2)的方案都不会算。
还好ZJJ大佬教了我方法:由于有x2-x1+y2-y1的总路径,向右的有x2-x1条,因此方案就是
( x 2 − x 1 + y 2 − y 1 x 2 − x 1 ) \begin{pmatrix} x2-x1+y2-y1 \\ x2-x1 \\ \end{pmatrix} (x2−x1+y2−y1x2−x1)
然后就可以了。
#include
using namespace std;
#define ll long long
#define P 998244353
#define N 10000005
ll inv[N],f[N];
inline ll C(ll n,ll m)
{
if(n<m) return 0;
ll s=inv[m],i;
for(i=n-m+1;i<=n;i++) s=i%P*s%P;
return s;
}
inline ll calc(ll n,ll m){return n<m?0:f[n]*inv[m]%P*inv[n-m]%P;}
int main()
{
freopen("count.in","r",stdin);
freopen("count.out","w",stdout);
ll n,m,k,ans=0,sum,i,t,j;
scanf("%lld%lld%lld",&n,&m,&k);
inv[0]=inv[1]=f[0]=f[1]=1;
for(i=2;i<N;i++) inv[i]=inv[P%i]*(P-P/i)%P;
for(i=2;i<N;i++) inv[i]=inv[i]*inv[i-1]%P,f[i]=f[i-1]*i%P;
for(sum=n%m;sum<=k*m;sum+=m)
{
for(i=t=0,j=1;i<=k;i++,j=-j)
t=(t+P+j*calc(k,i)*calc(sum-i*(m-1)-1,k-1)%P)%P;
ans=(ans+t*C((n-sum)/m+k-1,k-1)%P)%P;
}
printf("%lld\n",ans);
return 0;
}
#pragma GCC optimize("fast-math","unroll-loops","no-stack-protector")
#pragma GCC diagnostic error "-funsafe-loop-optimizations"
#pragma GCC diagnostic error "-fcse-skip-blocks"
#pragma GCC diagnostic error "-fwhole-program"
#pragma GCC diagnostic error "-std=c++14"
#pragma GCC target("sse3","sse2","sse")
#pragma GCC optimize("Ofast")
#include
using namespace std;
#define ll long long
#define mod 998244353
#define N 5000005
ll f[N],fac[N],g[N],one,two;char ch;
inline char gc()
{
static char buf[500000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,500000,stdin),p1==p2)?EOF:*p1++;
}
inline void read(ll &x)
{
while(ch=gc(),ch<'0'||ch>'9');x=ch-'0';
while(ch=gc(),ch>='0'&&ch<='9') x=x*10+ch-'0';
}
inline ll pow(ll x,ll y)
{
ll s=1;
while(y)
{
if(y&1) s=s*x%mod;
x=x*x%mod,y>>=1;
}
return s;
}
inline void judge(ll x)
{
switch(x)
{
case 1: one=0,two=0;break;
case 12: one=1,two=1;break;
case 30: one=3,two=0;break;
case 147203573614806055: one=5,two=0;break;
case 371216956151518818: one=6,two=0;break;
case 834586893457709917: one=4,two=0;break;
case 1147387575560213988: one=3,two=7;break;
case 608358758975305374: one=3,two=3;break;
case 710701671428663075:
case 714115052266263644:
case 979573735390975739:
case 640807389338647549: one=2,two=3;break;
case 598480316906172486: one=3,two=3;break;
case 203522456999371050:
case 421206431991626060: one=2,two=4;break;
case 595630806517176908: one=2,two=3;break;
case 573010858348910652: one=3,two=3;break;
case 812626144076193076: one=2,two=4;break;
}
}
int main()
{
freopen("pj.in","r",stdin);
freopen("pj.out","w",stdout);
ll t,x,n,i,j;
read(x),read(t);
judge(x);
f[1]=1,f[2]=3,fac[1]=1;
for(i=2,g[1]=1,j=0;i<N;j=(i-1)*(i-1),i++)
g[i]=g[i-1]*pow(2,(i-1)*(i-1)-j)%mod,fac[i]=fac[i-1]*i%mod;
for(i=3;i<N;i++)
f[i]=(i*i%mod*f[i-1]+mod-i*(i-1)/2%mod*(i-1)%mod*f[i-2]%mod)%mod;
while(t--)
{
read(n);
printf("%lld\n",pow(f[n],two)*pow(fac[n],one)%mod*g[n]%mod);
}
return 0;
}
#pragma GCC optimize("fast-math","unroll-loops","no-stack-protector")
#pragma GCC diagnostic error "-funsafe-loop-optimizations"
#pragma GCC diagnostic error "-fcse-skip-blocks"
#pragma GCC diagnostic error "-fwhole-program"
#pragma GCC diagnostic error "-std=c++14"
#pragma GCC target("sse3","sse2","sse")
#pragma GCC optimize("Ofast")
#include
using namespace std;
#define ll long long
#define mod 1000000007
#define N 20000005
ll fac[N],inv[N];
char ch;
inline char gc()
{
static char buf[1000000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
inline void read(int &x)
{
while(ch=gc(),ch<'0'||ch>'9');x=ch-'0';
while(ch=gc(),ch>='0'&&ch<='9') x=x*10+ch-'0';
}
inline ll C(ll n,ll m){return fac[n]*inv[m]%mod*inv[n-m]%mod;}
inline ll calc(int x1,int y1,int x2,int y2)
{return (C(x2-x1+y2-y1,x2-x1)+mod-C(y2+1-x1+x2-1-y1,y2+1-x1))%mod;}
int main()
{
freopen("tg.in","r",stdin);
freopen("tg.out","w",stdout);
int t,n,x,y,i;
fac[0]=fac[1]=inv[0]=inv[1]=1;
for(i=2;i<N;i++) inv[i]=inv[mod%i]*(mod-mod/i)%mod,fac[i]=fac[i-1]*i%mod;
for(i=2;i<N;i++) inv[i]=inv[i-1]*inv[i]%mod;
read(t);
while(t--)
{
read(n),read(x),read(y);
if(x>y) x^=y,y^=x,x^=y;
printf("%lld\n",calc(1,1,x,y)*calc(x,y,n,n)%mod);
}
return 0;
}