HDU6129(杨辉三角和万恶的Lucas)

菜死了,比赛的时候T到哭
表格中 ai 代表i个a异或

m a1 a2 a3 a4
1 a1 a1 ^ a2 a1 ^ a2 ^ a3 a1 ^ a2 ^ a3 ^ a4
2 a1 a21 ^ a2 a31 ^ a22 ^ a3 a41 ^ a32 ^ a23 ^ a4
3 a1 a31 ^ a2 a61 ^ a32 ^ a3 a101 ^ a62 ^ a33 ^ a4
4 a1 a41 ^ a2 a101 ^ a42 ^ a3 a201 ^ a102 ^ a43 ^ a4



很简单就可以找出其中系数的规律,对于异或而言,异或相同的数偶数次相当于没有异或,那么我们只需要找出其中奇数就可以了.
注意了万恶的Lucas定理: Cmn 是奇数当且仅当把a,b二进制表达后b中1的位置是a中1的位置的子集
比赛的时候根本不知道,用Lucas求组合数,T到哭.
TLE code:

#include
#include
#include
#include
#include
//a&3==a%4
using namespace std;
#define ll long long
#define mem(a) memset(a,0,sizeof(a))
const double eps=1e-8;
const int maxn=200010;//须填写
const int inf=0x3f3f3f3f;
const int p=1e9+7;
int a[maxn+10];
int b[maxn+10];
long long Pow(long long a,long long b)
{
    long long ans=1;
    while(b)
    {
        if(b&1)
        {
            b--;
            ans=(ans*a)%p;
        }
        b>>=1;
        a=(a*a)%p;
    }
    return ans;
}
long long C(long long n,long long m)
{
    if(nreturn 0;
    long long a=1,b=1;
    while(m)
    {
        a=(a*n)%p;
        b=(b*m)%p;
        m--;
        n--;
    }
    return (a*Pow(b,p-2))%p;
}
long long Lucas(long long n,long long m)
{
    if(m==0)
        return 1;
    return Lucas(n/p,m/p)*C(n%p,m%p)%p;
}
bool C(int n,int b)
{
    ll x=(ll)n;
    ll y=(ll)b;
    ll ans=Lucas(x,y);
    if(ans%2==1)
        return true;
    else return false;
}
int main()
{
    int kase;
    scanf("%d",&kase);
    while(kase--)
    {
        mem(a);
        mem(b);
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",a+i);
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=i;j>0;j--)
            {
                if(C(m-1+i-j,m-1))
                {
                    b[i]=b[i]^a[j];
                }

            }
        }
        for(int i=1;iprintf("%d ",b[i]);
        }
        printf("%d\n",b[n]);
    }
    return 0;
}

AC code:

#include
#include
#include
#include
#include
//a&3==a%4
using namespace std;
#define ll long long
#define mem(a) memset(a,0,sizeof(a))
const double eps=1e-8;
const int maxn=200010;//须填写
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
int a[maxn];
int b[maxn];
int main()
{
    int kase;
    scanf("%d",&kase);
    while(kase--)
    {
        mem(a);
        mem(b);
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",a+i);
        }
        for(int i=1;i<=n;i++)
        {
            int x=i+m-2;
            int y=i-1;
            if((x&y)==y)//y的1位置是x的子集则(x&y)==y
            {
                for(int j=i;j<=n;j++)
                    b[j]^=a[j-i+1];
            }
        }
        for(int i=1;iprintf("%d ",b[i]);
        }
        printf("%d\n",b[n]);
    }
    return 0;
}

你可能感兴趣的:(hdu,水题,数学,容斥定理,Lucas定理)