zoukankan      html  css  js  c++  java
  • hdu 5833 Zhu and 772002 ccpc网络赛 高斯消元法

    传送门:hdu 5833 Zhu and 772002

    题意:给n个数,每个数的素数因子不大于2000,让你从其中选则大于等于1个数相乘之后的结果为完全平方数

    思路:

    1. 小于等于2000的素数一共也只有305个
    2. 一个数,如果他某个素数因子的幂为偶,那这个素数的可以不用考虑;如果幂为奇数,那这个素数就应当被考虑如何与其他数凑成幂为偶数。例如12,可以表示为2^2*3,2的幂次为2,3的幂次为1,所以,如果要和其他数相乘为完全平方数,那么一定要与素数因子3为奇次的合并
    3. 那么根据上面两条,我们可以列出方程:x1*a11+x2*a12+...+xn*a1n=0;x为解,如果aii取为1,不取为0;aii表示ai的第i个素数因子是否为奇,是为1,否则为0,(素数按从小到大排序,依次为2,3,5,7...)
    4. 答案即为2^(x中自由元的个数)-1
    /**************************************************************
        Problem:hdu 5833 Zhu and 772002
        User: youmi
        Language: C++
        Result: Accepted
        Time:
        Memory:
    ****************************************************************/
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    //#include<bits/stdc++.h>
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <map>
    #include <stack>
    #include <set>
    #include <sstream>
    #include <cmath>
    #include <queue>
    #include <deque>
    #include <string>
    #include <vector>
    #define zeros(a) memset(a,0,sizeof(a))
    #define ones(a) memset(a,-1,sizeof(a))
    #define sc(a) scanf("%d",&a)
    #define sc2(a,b) scanf("%d%d",&a,&b)
    #define sc3(a,b,c) scanf("%d%d%d",&a,&b,&c)
    #define scs(a) scanf("%s",a)
    #define sclld(a) scanf("%I64d",&a)
    #define pt(a) printf("%d
    ",a)
    #define ptlld(a) printf("%I64d
    ",a)
    #define rep(i,from,to) for(int i=from;i<=to;i++)
    #define irep(i,to,from) for(int i=to;i>=from;i--)
    #define Max(a,b) ((a)>(b)?(a):(b))
    #define Min(a,b) ((a)<(b)?(a):(b))
    #define lson (step<<1)
    #define rson (lson+1)
    #define eps 1e-6
    #define oo 0x3fffffff
    #define TEST cout<<"*************************"<<endl
    const double pi=4*atan(1.0);
    
    using namespace std;
    typedef long long ll;
    template <class T> inline void read(T &n)
    {
        char c; int flag = 1;
        for (c = getchar(); !(c >= '0' && c <= '9' || c == '-'); c = getchar()); if (c == '-') flag = -1, n = 0; else n = c - '0';
        for (c = getchar(); c >= '0' && c <= '9'; c = getchar()) n = n * 10 + c - '0'; n *= flag;
    }
    ll Pow(ll base, ll n, ll mo)
    {
        if (n == 0) return 1;
        if (n == 1) return base % mo;
        ll tmp = Pow(base, n >> 1, mo);
        tmp = (ll)tmp * tmp % mo;
        if (n & 1) tmp = (ll)tmp * base % mo;
        return tmp;
    }
    //***************************
    
    int n;
    const ll mod=1000000007;
    const int maxn=50010;
    ll prime[maxn];
    bool isprime[maxn*20];
    int tot;
    int a[400][400];
    int x[400];
    int fre[400];
    int index;
    int tt=305;
    void prim()//素数筛法
    {
        tot=0;
        memset(isprime,true,sizeof(isprime));
        prime[tot++]=2;
        for(int i=3;i<maxn;i+=2)
        {
            if(isprime[i])
            {
                prime[tot++]=i;
                for(ll j=i;1ll*i*j<1ll*maxn;j+=2)
                    isprime[i*j]=false;
            }
        }
    }
    void solve(int i,ll x)//判断x有哪些素数因子的幂为奇
    {
        int cnt=0;
        rep(j,0,tot)
        {
            cnt=0;
            if(x%prime[j]==0)
            {
                while(x%prime[j]==0)
                {
                    cnt++;
                    x/=prime[j];
                }
            }
            if(cnt%2)
                a[i][j]=1;
            if(x==1)
                break;
        }
    }
    void debug(int rw,int cl)
    {
        rep(i,0,rw-1)
        {
            rep(j,0,cl-1)
                printf("%d ",a[i][j]);
            printf("
    ");
        }
    }
    int gauss(int rw,int cl)//高斯消元法,01异或
    {
        int i,j,k;
        int mx=0;
        for(i=0,j=0;i<rw&&j<cl-1;i++,j++)
        {
            mx=i;
            for(k=i;k<rw;k++)
            {
                if(abs(a[k][j])>abs(a[mx][j]))
                    mx=k;
            }
            if(mx!=i)
            {
                for(k=j;k<cl;k++)
                    swap(a[mx][k],a[i][k]);
            }
            if(a[i][j]==0)
            {
                i--;
                continue;
            }
            for(k=i+1;k<rw;k++)
            {
                if(a[k][j]!=0)
                {
                    for(int t=j;t<cl;t++)
                    {
                        a[k][t]^=a[i][t];
                    }
                }
            }
        }
        if(i<rw)
        {
            for(k=i-1;k>=0;k--)
            {
                int num=0;
                for(int t=0;t<cl;t++)
                {
                    if(a[k][t]!=0&&fre[t])
                        num++,index=t;
                }
                if(num>1)
                    continue;
                int temp=a[k][cl-1];
                for(int t=0;t<cl-1;t++)
                    if(a[k][t]!=0&&index!=t)
                        temp^=a[k][t]&&x[t];
                x[k]=temp&&a[k][k];
                fre[index]=0;
            }
            return rw-i;
        }
        return 0;
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
        #endif
        prim();
        int T;
        scanf("%d", &T);
        for (int kase = 1;kase <= T;kase++)
        {
            int n;
            scanf("%d", &n);
            zeros(a);
            zeros(x);
            memset(fre,1,sizeof(fre));
            for (int i=0;i<n;i++)
            {
                long long x;
                scanf("%I64d", &x);
                solve(i,x);
            }
            ll ans=gauss(n,tt);
            ans=(Pow(2,ans,mod)-1+mod)%mod;
            printf("Case #%d:
    %I64d
    ", kase,ans);
        }
        return 0;
    }
    不为失败找借口,只为成功找方法
  • 相关阅读:
    面试题
    iOS 两种方法实现左右滑动出现侧边菜单栏 slide view
    进程、线程、多线程相关总结
    iOS开发
    播放 视频
    delphi控件属性大全-详解-简介
    Cxgrid获取选中行列,排序规则,当前正在编辑的单元格内的值
    FastReport 使用说明
    delphi的取整函数round、trunc、ceil和floor
    cxGrid 速度
  • 原文地址:https://www.cnblogs.com/youmi/p/5773125.html
Copyright © 2011-2022 走看看