ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

NOIP提高组模拟赛夜间版1

2022-01-17 16:33:40  阅读:159  来源: 互联网

标签:... 夜间 pq gcd NOIP int long fib 模拟


由于上午考试出了其他大佬打过的原题,所以晚上加试

A. 中国象棋

一看题面,状压DP!一看数据范围\(N,M<=100\)。。。

实际可以发现,每行每列最多放两个炮,统计方案数的话具体在哪里是无所谓的

定义f[i][j][k]表示前i行有j个位置放了1个棋子,k个位置一个棋子都没放的方案数

初始状态f[0][0][m]=1;

分类讨论

不放\(f[i][j][k]=f[i-1][j][k]\)

放1个棋子在之前没放过的列,有\((k+1)\)种放法\(f[i][j][k]+=f[i-1][j-1][k+1]*(k+1)\)

放1个棋子在之前放过一个的列,有\((j+1)\)种放法\(f[i][j][k]+=f[i-1][j+1][k]*(j+1)\)

放2个棋子在之前没放过的列,有\((k+1)*(k+2)/2\)种放法\(f[i][j][k]+=f[i-1][j-2][k+2]*(k+1)*(k+2)/2\)

放2个棋子在之前放过1个的列,有\((j+1)*(j+2)\)种放法\(f[i][j][k]+=f[i-1][j+2][k]*(j+1)*(j+2)/2\)

放1个棋子在之前放过1个的列,1个棋子在之前没放过的列,有\(j*(k+1)\)种放法\(f[i][j][k]+=f[i-1][j][k+1]*j*(k+1)\)

记得取模,去掉减法减出负数的越界

最后答案对\(f[n][j][k](j\in[0,m],k\in[0,m])\)求和

#include<cstdio>
#include<algorithm>
using namespace std;
const int mod=9999973;
int n,m;
long long f[105][105][105];
int main(){
    scanf("%d%d",&n,&m);
    f[0][0][m]=1;//f[i][j][k] i行j个1k个0
    for(int i=1;i<=n;++i){
        for(int j=0;j<=m;++j){
            for(int k=0;k<=m;++k){
                f[i][j][k]+=f[i-1][j][k];//不放
                if(j)f[i][j][k]+=f[i-1][j-1][k+1]*(k+1);//放一个在没放过的列
                f[i][j][k]+=f[i-1][j+1][k]*(j+1);  //放一个在放过1个的列
                if(j>=2)f[i][j][k]+=f[i-1][j-2][k+2]*(k+2)*(k+1)/2;//放两个在没放过的列
                f[i][j][k]+=f[i-1][j+2][k]*(j+2)*(j+1)/2;//放两个在放过一个的列
                f[i][j][k]+=f[i-1][j][k+1]*j*(k+1);//放一个在没放过的列,1个在放过1个的列
                f[i][j][k]=f[i][j][k]%mod;
            }
        }
    }
    long long ans=0;
    for(int i=0;i<=m;++i)
      for(int j=0;j<=m;++j)
        ans=(ans+f[n][i][j])%mod;
    printf("%lld\n",ans);
    return 0;
}

B. 奇妙的 Fibonacci

奇妙奇妙,太奇妙了,大爱数论

感觉会敲latex到吐,提前祭奠一下

先说简单不用latex

考场直接打表,先敲个暴力,然后换用不同放法妄图探究性质,然后在输出第i项Fibonacci能整除第几项时发现了规律打表万岁,除了第二项特殊,其他第i项能整除第\(i,2*i,3*i,4*i.....k*i\)项,看到这个自然想到了埃氏筛,
yy了一下复杂度感觉能过,打完跑路,喜提TLE。线性筛也不会求这玩意啊

再来严谨的证明

\(fib[i]=fib[i-1]+fib[i-2]\)

\(=fib[i-1]*fib[2]+fib[i-2]*fib[1]\)

\(=(fib[i-2]+fib[i-3])*fib[2]+fib[i-2]*fib[1]\)

\(=fib[i-2]*fib[3]+f[i-3]f[2].........\)

同理可继续推下去有

\(fib[i]=fib[i-k+1]*fib[k]+fib[i-k]*fib[k-1]\)

即 \(fib[n+m]=fib[n]*fib[m+1]+fib[n-1]*fib[m]\) ......................\((1)\)

\(gcd(f_{i},f_{i-1})=gcd(f_{i}-f_{i-1},f_{i-1})=gcd(f_{i-2},f_{i-1})=....=gcd(f_{1},f_{2})=1\)......................\((2)\)

(因为(1))

\(gcd(fib_{n+m},fib_{m})=gcd(fib_{n-1}*fib_{m}+fib_{n}*fib_{m+1},fib_{m})\)

\(=gcd(fib_{n-1}*fib_{m}+fib_{n}*fib_{m+1}-fib_{m}-fib_{m}-fib_{m}...,fib_{m})\)

\(=gcd(fib_{n}*fib_{m+1},fib_{m})\)

(因为(2))

\(=gcd(fib_{n},fib_{m})\)

上式\(gcd(fib_{n+m},fib_{m})=gcd(fib_{n},fib_{m})\)与\(gcd(n+m,m)=gcd(n,m)\)类比

可以得出,对于相同n,m上述两个整除关系同时成立,也就是说\(i|j时fib_{i}|fib_{j}\)

这就是我打表打出的那个性质,也是解决问题的第一个关键点

经过这样的证明,我们可以将原问题转化为

对于i求i的约数个数和i约数的平方和

如何解决这个问题

考虑使用埃氏筛线性筛

定义

\(a[i]\)为i约数个数

\(b[i]\)为i约数平方和

\(c[i]\)为i最小质因子的幂

\(d[i]\)为i除去最小质因子后剩下的数

显然\(a[i],b[i]\)是积性函数

证明

\(m\perp n\)

\(m=p_{1}^{c1}p_{2}^{c2}p_{3}^{c3}...p_{n}^{cn}\)

\(a[m]=(c1+1)*(c2+1)*(c3+1)...(cn+1)\)

\(n=q_{1}^{x1}q_{2}^{x2}q_{3}^{x3}...q_{n}^{xn}\)

\(a[n]=(x1+1)*(x2+1)*(x3+1)...(xn+1)\)

\(mn=p_{1}^{c1}p_{2}^{c2}p_{3}^{c3}...p_{n}^{cn}q_{1}^{x1}q_{2}^{x2}q_{3}^{x3}...q_{n}^{xn}\)

\(a[mn]=(c1+1)*(c2+1)*(c3+1)...(cn+1)*(x1+1)*(x2+1)*(x3+1)...(xn+1)=a[m]*a[n]\)

关于\(b[i]\),用乘法分配律证明,过程。。。YY一下吧

大概就是对于n中每个因子,与m的每个因数相乘可以得到mn的一个因数,对平方和的贡献就是新因数的平方,也就是m因数的平方乘以n该因子的平方,将这串式子中的该因子平方提出来就能用b[m]和该因子表示新的平方和的一部分,而将所有n的因子都这样处理,可以YY得到\(b[mn]=b[m]b[n]\) \((m\perp n)\)

然后貌似就可以筛了

质数q \(A[q]=2\;\;B[q]=1+q^2\;\;C[q]=1\;\;D[q]=1\)

当$gcd(p,q)=1 $ 即\(i\;mod\;prime[j]!=0\)

$ A[pq]=A[p]A[q] ;;; B[pq]=B[p]B[q] ;;; C[pq]=1 ;;; D[pq]=p。$

当q|p时,即\(i\;mod\;prime[j]==0\)

\( A[pq]=A[p]/(C[p]+1)*(C[p]+2) \;\;\; B[pq]=B[p]+B[D[p]]*(p/D[p])^2 \)

\( C[pq]=C[p]+1 \;\;\; D[pq]=D[p]\)

解释一下\( A[pq]=A[p]/(C[p]+1)*(C[p]+2) \;\;\; B[pq]=B[p]+B[D[p]]*(p/D[p]*q)^2 \)

类似上面对积性的证明,考虑q这个质数(prime[j])对p因数的贡献,是\(q^{k}(k\in[0,c[p]])\)乘上不含q的因数,不含q的因数就有\(a[p]/(c[p]+1)\)个,现在有\(c[p]+1\)个q因子,那么对pq因子个数贡献就乘上\(c[p]+2\)

\(b[pq]\)与此类似,q对pq平方和的贡献是p中不含q的因数平方和乘上\(q^{c[p]+1}\)得出\(b[pq]=b[p]+b[d[p]]*q^{2c[p]+2}\),打快速幂也可,但是这个式子显然可以转化,因为\(p/d[p]=q^{c[p]}\),所以可以得到上式

最后因为\(fib_{2}=1\)是所有数的因数,所有奇数的a[i]需要++,不特判1,因为没说j小于i

#include<cstdio>
#include<cstring>

using namespace std;

const long long mod=1000000007;
const int maxx=10000007;
int ask[3000005];
long long a[maxx],b[maxx],c[maxx],d[maxx],prime[maxx];
bool flag[maxx];

int main(){
    int Q;scanf("%d",&Q);
    long long q,A,B,C;
    scanf("%lld%lld%lld%lld",&q,&A,&B,&C);
    for(int ass=1;ass<=Q;++ass){
        ask[ass]=q;
        q=(q*A+B)%C+1;
    }
    int cnt=0;
    a[1]=1,b[1]=1;
    for(int i=2;i<=C;++i){
        if(!flag[i]){
            prime[++cnt]=i;
            a[i]=2;b[i]=(1ll*i*i+1)%mod;c[i]=1;d[i]=1;
        }
        for(int j=1;j<=cnt&&prime[j]*i<=C;++j){
            int pq=i*prime[j];
            flag[pq]=1;
            if(i%prime[j]==0){
                a[pq]=(a[i]/(c[i]+1)*(c[i]+2))%mod;
                b[pq]=(b[i]+b[d[i]]*(i/d[i]*prime[j])*(i/d[i]*prime[j]))%mod;
                c[pq]=c[i]+1;
                d[pq]=d[i];
                break;
            }
            a[pq]=(1ll*a[i]*a[prime[j]])%mod;
            b[pq]=(1ll*b[i]*b[prime[j]])%mod;
            c[pq]=1;d[pq]=i;
        }

    }
    long long ans1=0,ans2=0;
    for(int i=1;i<=Q;++i){
        ans1=(ans1+a[ask[i]])%mod;
        ans2=(ans2+b[ask[i]])%mod;
        if(ask[i]&1){
            ans1++;
            ans2+=4;
        }
    }
    printf("%lld\n%lld\n",ans1%mod,ans2%mod);
    return 0;
}

貌似Day1神奇的函数不用暴力%prime[j],借鉴本题一小部分处理就行。

标签:...,夜间,pq,gcd,NOIP,int,long,fib,模拟
来源: https://www.cnblogs.com/Chencgy/p/15814007.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有