Contest 1

  A:注意到模数是要求lcm的数的倍数,直接先取模就可以了。考场脑抽,对其质因数分解判了一下每个因子有没有,当然也行。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
#define P 1234567890
int a=246913578;
int a2,a9,a3607,a3803,aP;
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int main()
{
    freopen("lcm.in","r",stdin);
    freopen("lcm.out","w",stdout);
    char c=getchar();
    while (c>='0'&&c<='9')
    {
        int x=c^48;
        a2=x&1;
        a9=(a9*10+x)%9;
        a3607=(a3607*10+x)%3607;
        a3803=(a3803*10+x)%3803;
        aP=(10ll*aP+x)%P;
        c=getchar();
    }
    if (a2) aP=2ll*aP%P;
    if (a3607) aP=3607ll*aP%P;
    if (a3803) aP=3803ll*aP%P;
    if (a9)
        if (a9%3==0) aP=3ll*aP%P;
        else aP=9ll*aP%P;
    cout<<aP;
    return 0;
}
View Code

  B:学傻系列。排列计数一般将数从小到大加进去考虑,于是设f[i][j]为i个数的排列其中有j个位置不合法的方案数,考虑每次往里加i+1,可以发现如果在上升段每个数的左侧或下降段每个数的右侧插入会使不合法位置--,反之则++。特殊情况是开头的下降段和结尾的上升段,于是增加二维01记录。正解考虑最大值出现位置于是变成了优美的卷积形式。当然原题n只有1000我的辣鸡dp也能A了。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
#define N 1010
int n,m,f[N][N][2][2]; //head tail up 0 down 1
void inc(int &x,int y){x+=y;if (x>=m) x-=m;}
int main()
{
    freopen("irrev.in","r",stdin);
    freopen("irrev.out","w",stdout);
    n=read(),m=read();
    if (n==1) {cout<<1;return 0;}
    if (n==2) {cout<<2;return 0;} 
    f[3][0][1][0]=2,f[3][0][0][1]=2,f[3][1][0][0]=1,f[3][1][1][1]=1; 
    for (int i=3;i<n;i++)
        for (int j=0;j<=i-2;j++)
            for (int x=0;x<=1;x++)
                for (int y=0;y<=1;y++)
                {
                    if (x==0) inc(f[i+1][j][1][y],f[i][j][x][y]);
                    else
                    {
                        inc(f[i+1][j+1][1][y],f[i][j][x][y]);
                        inc(f[i+1][j][0][y],f[i][j][x][y]); 
                    }
                    if (y==1) inc(f[i+1][j][x][0],f[i][j][x][y]);
                    else
                    {
                        inc(f[i+1][j+1][x][0],f[i][j][x][y]);
                        inc(f[i+1][j][x][1],f[i][j][x][y]);
                    }//head&&tail&&special check
                    if (j) inc(f[i+1][j-1][x][y],1ll*f[i][j][x][y]*j%m);
                    inc(f[i+1][j+1][x][y],1ll*f[i][j][x][y]*(i-1-j-(x==1)-(y==0))%m); 
                } 
    cout<<((f[n][0][0][0]+f[n][0][0][1])%m+(f[n][0][1][0]+f[n][0][1][1])%m)%m;
    return 0;
}
View Code

  C:找规律容易发现系数是组合数。(伪)扩展lucas或者质因数分解都可以。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
#define N 1050
#define P 100007 
int n,m,a[N],f[2][N],C[N],C0[2][N],fac[2][N],inv[2][N]; 
int lucas(int x,int n,int m,int p)
{
    if (m>n) return 0;
    if (n<p) return 1ll*fac[x][n]*inv[x][n-m]%p*inv[x][m]%p; 
    return 1ll*lucas(x,n%p,m%p,p)*lucas(x,n/p,m/p,p)%p; 
} 
void getC(int x,int p)
{
    fac[x][0]=1;for (int i=1;i<p;i++) fac[x][i]=1ll*fac[x][i-1]*i%p;
    inv[x][0]=inv[x][1]=1;for (int i=2;i<p;i++) inv[x][i]=p-1ll*(p/i)*inv[x][p%i]%p;
    for (int i=1;i<p;i++) inv[x][i]=1ll*inv[x][i-1]*inv[x][i]%p; 
    for (int i=0;i<=n;i++) C0[x][i]=lucas(x,m,i,p);
}
int getinv(int x,int y)
{
    for (int i=1;i<y;i++)
    if (1ll*i*x%y==1) return i; 
} 
void crt()
{
    int a=getinv(97,1031),b=getinv(1031,97);
    for (int i=0;i<=n;i++)
    C[i]=(1ll*C0[0][i]*1031%P*b%P+1ll*C0[1][i]*97%P*a%P)%P; 
} 
int main()
{
    freopen("difer.in","r",stdin);
    freopen("difer.out","w",stdout);
    n=read(),m=read();
    for (int i=1;i<=n;i++) a[i]=read();
    getC(0,97);getC(1,1031);
    crt(); 
    for (int i=0;i<=n;i++) if (i&1) C[i]=P-C[i]; 
    for (int i=1;i<=n;i++)
    { 
        int x=0; 
        for (int j=i;j>=1&&i-j<=m;j--) 
        x=(x+1ll*C[i-j]*a[j]%P)%P; 
        cout<<x<<endl;
    } 
    return 0; 
}
View Code

   result:300 rank1

转载于:https://www.cnblogs.com/Gloid/p/9734755.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值