2019年9月14日(数论专题考试)

Posted alanallen21love28

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2019年9月14日(数论专题考试)相关的知识,希望对你有一定的参考价值。

汗~,差点爆零(QwQ)……

(prob2:saber)

(upd):题意以后都不写了,反正写了日期,去文件里找。

题目数学?可惜我开始跑的是暴力……

思路肯定是总方案减去不合法方案,那么就有两种主流思路:

暴力30分,因为不合法情况是且仅是要到达灰线上面一条线的任一个点,那么可以算方案。考虑(dp)式,设(f_i)为到达目标线上的第(i)个点且未经过之前(i-1)个点的总方案数,(s_i)表示目标线上第(i)个点到起点的方案数,(t_i)表示目标线上第(i)个点到终点的方案数,(p_{i,j}(i<j))表示目标线上第(i)个点到第(j)个点的方案数,则
[f_i=s_i-sum_{j=1}^{i-1}f_j* p_{j,i}]
[ans=C_{n+m}^m-sum_{i=1}^mf_i* t_i]
时间复杂度(O(m^2)),实际得分40分:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define in read()
#define re register
#define fur(i,a,b) for(re int i=a;i<=b;++i)
#define fdr(i,a,b) for(re int i=a;i>=b;--i)
#define cl(a,b) memset(a,b,sizeof(a))
#define jinitaimei signed
#define int long long
inline int read()
{
    int x=0;
    char ch=getchar();
    for(;!isalnum(ch);ch=getchar());
    for(;isalnum(ch);ch=getchar()) x=x*10+ch-'0';
    return x;
}
const int mod=2e7-1;
const int xx=1e5+1612;
int jc[xx],ny[xx],f[xx];
inline int power(int x,int k)
{
    int res=1;
    for(;k;x=x*x%mod,k>>=1) if(k&1) res=res*x%mod;
    return res;
}
inline int C(int n,int m)
{
    return jc[n]*ny[m]%mod*ny[n-m]%mod;
}
jinitaimei main()
{
    int n=in,m=in;
    jc[0]=ny[0]=1;
    fur(i,1,n+m) jc[i]=jc[i-1]*i%mod,ny[i]=power(jc[i],mod-2);
    fur(i,0,m-1) f[i+1]=C(i+i+2,i);
    fur(i,1,m) fur(j,1,i-1) f[i]=(f[i]-f[j]*C((i-j)<<1,i-j)%mod+mod)%mod;
    int ans=C(n+m,n);
    fur(i,1,m) ans=(ans-f[i]*C(n-(i-1)+m-(i+1),n-(i-1))%mod+mod)%mod;
    cout<<ans<<endl;
    return 0;
}

正解,发现对称算一下(ans=C_{n+m}^m-C_{n+m}^{m-2})
虽然(n,m)比较大,但发现(mod=2e7-1)比较小,于是卢卡斯

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define in read()
#define re register
#define fur(i,a,b) for(re int i=a;i<=b;++i)
#define fdr(i,a,b) for(re int i=a;i>=b;--i)
#define cl(a,b) memset(a,b,sizeof(a))
#define jinitaimei signed
#define int long long
inline int read()
{
    int x=0;
    char ch=getchar();
    for(;!isalnum(ch);ch=getchar());
    for(;isalnum(ch);ch=getchar()) x=x*10+ch-'0';
    return x;
}
const int mod=2e7-1;
int jc[mod];
inline int power(int x,int k)
{
    int res=1;
    for(;k;x=x*x%mod,k>>=1) if(k&1) res=res*x%mod;
    return res;
}
inline int lucas(int n,int m)
{
    if(n<mod&&m<mod)
    {
        if(n<m) return 0;
        return jc[n]*power(jc[m],mod-2)%mod*power(jc[n-m],mod-2)%mod;
    }
    return lucas(n%mod,m%mod)*lucas(n/mod,m/mod)%mod;
}
jinitaimei main()
{
    int n=in,m=in;
    jc[0]=1;
    fur(i,1,mod) jc[i]=jc[i-1]*i%mod;
    cout<<(lucas(n+m,m)-lucas(n+m,m-2)+mod)%mod<<endl;
    return 0;
}

于是正解比暴力还短……

(prob3:)不够优秀((good))

很明显发现这个东西其实是求(sum_{i=1}^nd_i* (d_i-1)/2)

70分就是暴力求,时间复杂度(O(nsqrt n)):

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define in read()
#define re register
#define fur(i,a,b) for(re int i=a;i<=b;++i)
#define fdr(i,a,b) for(re int i=a;i>=b;--i)
#define cl(a,b) memset(a,b,sizeof(a))
#define jinitaimei signed
#define int long long
inline int read()
{
    int x=0;
    char ch=getchar();
    for(;!isalnum(ch);ch=getchar());
    for(;isalnum(ch);ch=getchar()) x=x*10+ch-'0';
    return x;
}
const int mod=998244353;
const int ny2=499122177;
inline int power(int x,int k)
{
    int res=1;
    for(;k;x=x*x%mod,k>>=1) if(k&1) res=res*x%mod;
    return res;
}
jinitaimei main()
{
    int n=in;
    if(n==1)
    {
        cout<<"0"<<endl;
        return 0;
    }
    int ans=0;
    fur(i,2,n)
    {
        int all=0,j=i;
        for(int k=1;k*k<=j;++k) if(!(j%k))
                             {
                                 ++all;
                                 if(k*k!=j) ++all;
                             }
        ans=((all-1)*all%mod*ny2%mod+ans)%mod;
    }
    printf("%lld
",ans);
    return 0;
}

正解线性筛即可,时间复杂度(O(n)):

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
#define in read()
#define re register
#define fur(i,a,b) for(re int i=a;i<=b;++i)
#define fdr(i,a,b) for(re int i=a;i>=b;--i)
#define cl(a,b) memset(a,b,sizeof(a))
#define jinitaimei signed
#define int long long
inline int read()
{
    int x=0;
    char ch=getchar();
    for(;!isalnum(ch);ch=getchar());
    for(;isalnum(ch);ch=getchar()) x=x*10+ch-'0';
    return x;
}
const int mod=998244353;
const int ny2=499122177;
int d[10000001],e[10000001];
int prime[10000001],n,ans=0,cnt=0;
bool to[10000001];
inline void init()
{
    fur(i,2,n)
    {
        if(!to[i])
        {
            prime[++cnt]=i;
            d[i]=2;
            e[i]=1;
        }
        fur(j,1,cnt)
        {
            if(i*prime[j]>n) break;
            to[i*prime[j]]=true;
            if(i%prime[j])
            {
                d[i*prime[j]]=d[i]*2;
                e[i*prime[j]]=1;
            }
            else
            {
                d[i*prime[j]]=d[i]/(e[i]+1)*(e[i]+2);
                e[i*prime[j]]=e[i]+1;
                break;
            }
        }
    }
}
jinitaimei main()
{
    n=in;
    init();
    fur(i,1,n) ans=(ans+d[i]*(d[i]-1)%mod*ny2%mod)%mod;
    cout<<ans<<endl;
    return 0;
}
  

(prob1:)摆干草((bales))

额,没想到是数据结构……

二分,然后并查集维护最小区间,查看与现在搜到的是否矛盾即可

每当查到一个(mid),将(mid)及之前的按(A)值从大到小排序,查看是否有大区间覆盖小区间即可

这个二分有点毒瘤……

时间复杂度(O(Nalpha NlogQ)):

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define in read()
#define re register
#define fur(i,a,b) for(re int i=a;i<=b;++i)
#define fdr(i,a,b) for(re int i=a;i>=b;--i)
#define cl(a,b) memset(a,b,sizeof(a))
#define jinitaimei signed
//#define int long long
inline int read()
{
    int x=0;
    char ch=getchar();
    for(;!isalnum(ch);ch=getchar());
    for(;isalnum(ch);ch=getchar()) x=x*10+ch-'0';
    return x;
}
const int xx=1e6+1612,yy=2e5+1612;
int fa[xx],n,m;
struct line
{
    int l,r;
    int val;
}L[yy],tmp[yy];
inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
inline bool cmp(line x,line y){return x.val>y.val;}
inline bool check(int x)
{
    fur(i,1,n+1) fa[i]=i;
    fur(i,1,x) tmp[i]=L[i];
    sort(tmp+1,tmp+1+x,cmp);
    int l1,l2,r1,r2;
    l1=l2=tmp[1].l;r1=r2=tmp[1].r;
    fur(i,2,x)
    {
        if(tmp[i].val<tmp[i-1].val)
        {
            if(find(l1)>r1) return false;
            for(int j=fa[l2];j<=r2;j=fa[j]) find(j),fa[j]=find(j+1);
            l1=l2=tmp[i].l;
            r1=r2=tmp[i].r;
        }
        else
        {
            l1=max(l1,tmp[i].l);
            l2=min(l2,tmp[i].l);
            r1=min(r1,tmp[i].r);
            r2=max(r2,tmp[i].r);
            if(r1<l1) return false;
        }
    }
    if(find(l1)>r1) return false;
    return true;
}
jinitaimei main()
{
    freopen("bales.in","r",stdin);
    freopen("bales.out","w",stdout);
    n=in,m=in;
    fur(i,1,m) L[i]=(line){in,in,in};
    int l=1,r=m+1;
    while(l<r)
    {
        int mid=(l+r)>>1;
        if(check(mid)) l=mid+1;
        else r=mid;
    }
    if(l>m) puts("0");
    else printf("%d
",l);
    return 0;
}

(prob4:)闷声发大财((rich))

30分:考虑状压,明确状态(f_{A,B})为龙选(A)(hyj)(b)的方案数,压的是因数

压根没想到,于是没写,不给代码了……

正解:考虑状压优化,将(2-n)的每个数(i)(sqrt i)之内的质因数状压出来,其余暴力枚,用数组(f_{0/1,A,B})表示即为龙或(hyj)选了当前数(i)的大于(sqrt i)的那一个质因数且龙集合(A)(hyj)集合(B)的方案数,可以推出来递推式……

(sqrt {500})以内的质数只有(8)个,可以放心状压……

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define in read()
#define re register
#define fur(i,a,b) for(re int i=a;i<=b;++i)
#define fdr(i,a,b) for(re int i=a;i>=b;--i)
#define cl(a,b) memset(a,b,sizeof(a))
#define jinitaimei signed
#define int long long
inline int read()
{
    int x=0;
    char ch=getchar();
    for(;!isalnum(ch);ch=getchar());
    for(;isalnum(ch);ch=getchar()) x=x*10+ch-'0';
    return x;
}
const int maxp(8),maxn(501);
int prime[8]={2,3,5,7,11,13,17,19};
int n,mod,ans=0;
int f[2][1<<maxp][1<<maxp],g[1<<maxp][1<<maxp];
struct number{int numset,bignum;}a[maxn];
inline bool cmp(number x,number y){return (x.bignum^y.bignum)?(x.bignum>y.bignum):(x.numset<y.numset);}
inline void up(int &x,int y){(x+=y)%=mod;}
inline void init()
{
    n=in;mod=in;
    fur(i,2,n)
    {
        int x=i;
        fur(j,0,7) if(!(x%prime[j]))
        {
            a[i].numset+=(1<<j);
            while(!(x%prime[j])) x/=prime[j];
        }
        a[i].bignum=x;
    }
    sort(a+2,a+n+1,cmp);
    g[0][0]=1;
}
inline void sol()
{
    fur(i,2,n)
    {
        if(i==2||a[i].bignum==1||a[i].bignum^a[i-1].bignum) memcpy(f[0],g,sizeof(g)),memcpy(f[1],g,sizeof(g));
        fdr(j,(1<<maxp)-1,0) fdr(k,(1<<maxp)-1,0)
        {
            if(!(j&a[i].numset)) up(f[0][j][k|a[i].numset],f[0][j][k]);
            if(!(k&a[i].numset)) up(f[1][j|a[i].numset][k],f[1][j][k]);
        }
        if(i==n||a[i].bignum==1||a[i].bignum^a[i+1].bignum)
            fdr(j,(1<<maxp)-1,0) fdr(k,(1<<maxp)-1,0) g[j][k]=(f[0][j][k]+f[1][j][k]-g[j][k]+mod)%mod;
    }
}
jinitaimei main()
{
    init();
    sol();
    fdr(j,(1<<maxp)-1,0) fdr(k,(1<<maxp)-1,0) if(!(j&k)) up(ans,g[j][k]);
    cout<<ans<<endl;
    return 0;
}

(ps:xg)真是一只毒瘤的鸡

以上是关于2019年9月14日(数论专题考试)的主要内容,如果未能解决你的问题,请参考以下文章

;~ 小部分AutoHotkey源代码片段测试模板2019年10月9日.ahk

关于2019年3月30日项目管理资格认证考试的报名通知

9.24 11.5 12.14

2019年9月14日

号外!2019月3月PMP项目管理认证考试报名通知

系统架构设计师考试介绍