10.15测试

T1 pay

Sol
扩欧求最小解,然后计算方案数和总和。注意一细节即可。不过我根本没写扩欧,我求最小解用的暴力...但是可以证明暴力的时间复杂度不超过\(O(\sqrt n)\)
Code

#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read()
{
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=0;c=getchar();}
    while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c&15),c=getchar();
    return f?x:-x;
}
inline int gcd(int x,int y)
{
    while(y){int t=y;y=x%y;x=t;}
    return x;
}
int T,opt,a,b,c,ans1,ans2;
inline void getans()
{
    ans1=ans2=0;
    int g=gcd(a,b);
    if(c%g!=0)return;
    a/=g;b/=g;c/=g;
    if(a>b)swap(a,b);
    if(c<b)
    {
        if(c%a==0)ans1=1,ans2=c/a;
        return;
    }
    if(c<=a*b)
    {
        for(int i=0;i<=c/b;i++)
        {
            if((c-b*i)%a==0)
            {
                ans1=1;ans2=i+(c-b*i)/a;
                return;
            }
        }
        return;
    }
    int ti=c/(a*b)-1;
    c=c%(a*b)+a*b;
    for(int i=0;i<=c/b;i++)
    {
        if((c-b*i)%a==0)
        {
            if(c-b*i>=a*b)
            {
                ans1=ti+2;
                int fi=i+(c-b*i-a*b)/a+(ti+1)*a;
                int la=i+(c-b*i-a*b)/a+(ti+1)*b;
                ans2=(fi+la)*ans1/2;
                return;
            }else
            {
                ans1=ti+1;
                int fi=i+(c-b*i)/a+ti*a;
                int la=i+(c-b*i)/a+ti*b;
                ans2=(fi+la)*ans1/2;
                return;
            }
        }
    }
    return;
}
signed main()
{
    freopen("pay.in","r",stdin);
    freopen("pay.out","w",stdout);
    T=read();opt=read();
    while(T--)
    {
        a=read();b=read();c=read();
        getans();
        if(opt==1)printf("%lld\n",ans1);
        else printf("%lld %lld\n",ans1,ans2);
    }
}

T2 sumcomb

Sol
把求的两种答案拆解一下容易发现就是平移后的杨辉三角。证明如下:讲定义中的一列求解,把每一项在杨辉三角中拆开,就变成了两列,所以依然符合杨辉三角的性质,初始值特殊处理即可。对于斜着的讲杨辉三角翻转后与竖直的情况一样。
Code

#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read()
{
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=0;c=getchar();}
    while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c&15),c=getchar();
    return f?x:-x;
}
const int p=1000000007,maxn=1000010;
int T,n,m,opt;
int fac[maxn],facinv[maxn];
inline int ksm(int x,int mi)
{
    int ans=1;
    while(mi)
    {
        if(mi&1)ans=ans*x%p;
        x=x*x%p;mi>>=1;
    }
    return ans;
}
inline void pre(int mx)
{
    fac[0]=facinv[0]=1;
    for(int i=1;i<=mx;i++)fac[i]=fac[i-1]*i%p;
    facinv[mx]=ksm(fac[mx],p-2);
    for(int i=mx-1;i;i--)facinv[i]=facinv[i+1]*(i+1)%p;
    return;
}
inline int C(int x,int y)
{
//    cout<<fac[x]<<" "<<facinv[y]<<" "<<facinv[x-y]<<endl;
    return fac[x]*facinv[y]%p*facinv[x-y]%p;
}
signed main()
{
    freopen("sumcomb.in","r",stdin);
    freopen("sumcomb.out","w",stdout);
    T=read();pre(1000000);
    while(T--)
    {
        int opt=read(),n=read(),m=read();
        if(n<m)
        {
            printf("0\n");
            continue;
        }
        if(opt==2)m=n-m;
        printf("%lld\n",C(n+1,m+1));
    }
    return 0;
}
//C(n+1,m+1)

T3 kor

Sol
容斥原理+反演,搞不懂。
Code(贺的)

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int p=1000000007,maxn=100010,P=20;
inline int read()
{
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=0;c=getchar();}
    while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c&15),c=getchar();
    return f?x:-x;
}
int T,n,k,r;
int a[maxn],t[(1<<20)+10];
int fac[maxn],facinv[maxn],pw[maxn];
inline int ksm(int x,int mi)
{
    int ans=1;
    while(mi)
    {
        if(mi&1)ans=ans*x%p;
        x=x*x%p;mi>>=1;
    }
    return ans;
}
inline void pre(int mx)
{
    fac[0]=facinv[0]=pw[0]=1;
    for(int i=1;i<=P;i++)pw[i]=pw[i-1]<<1;
    for(int i=1;i<=mx;i++)fac[i]=fac[i-1]*i%p;
    facinv[mx]=ksm(fac[mx],p-2);
    for(int i=mx-1;i;i--)facinv[i]=facinv[i+1]*(i+1)%p;
    return;
}
inline int C(int x,int y)
{
    return fac[x]*facinv[y]%p*facinv[x-y]%p;
}
inline void workz()
{
    for(int i=0;i<P;i++)
    {
        int now=(pw[P]-1)^pw[i];
        for(int j=now;j;j=now&(j-1))
        {
            t[j|pw[i]]+=t[j];
            if(t[j|pw[i]]>=p)t[j+pw[i]]-=p;
        }
        t[pw[i]]+=t[0];
        if(t[pw[i]]>=p)t[pw[i]]-=p;
    }
    return;
}
inline void workf()
{
    for(int i=0;i<P;i++)
    {
        int now=(pw[P]-1)^pw[i];
        for(int j=now;j;j=now&(j-1))
        {
            t[j|pw[i]]-=t[j];
            if(t[j|pw[i]]<0)t[j+pw[i]]+=p;
        }
        t[pw[i]]-=t[0];
        if(t[pw[i]]<0)t[pw[i]]+=p;
    }
    return;
}
signed main()
{
    freopen("kor.in","r",stdin);
    freopen("kor.out","w",stdout);
    T=read();pre(100000);
    while(T--)
    {
        memset(t,0,sizeof(t));
        n=read();k=read();r=read();
        for(int i=1;i<=n;i++)
        {
            a[i]=read();t[a[i]]++;
        }
        workz();
        for(int i=0;i<pw[P];i++)
        {
            t[i]=C(t[i],k);
        }
        workf();
        printf("%lld\n",t[r]);
    }
    return 0;
}
posted @ 2021-10-15 21:46  wwlvv  阅读(29)  评论(0)    收藏  举报