HDU 4610(数论+枚举状态)

来源:互联网 发布:淘宝店铺引流工具 编辑:程序博客网 时间:2024/05/20 09:44

若x=a0^p0*a1^p1*……*ai^pi(a0,a1……,ai是不同的素数)

对于条件3:因子和=(a0^0+a0^1+……+a0^p0)*(a1^0+a1^1+……+a1^p1)*……

如果是素数,显然质因子个位要为1,并且(a0^(p0+1)-1)/(a0-1)为素数

对于条件4:设因子积为a0^q0*a1^q1*……*ai^qi(a0,a1……,ai是不同的素数)

则有qi=(pi*pi+1)/2*(p0+1)*(p1+1)……(p(i-1)+1),判断所有的qi是不是偶数即可

#include <cstdio>#include <cstring>#include <string>#include <iostream>#include <map>#include <vector>#include <cmath>#include <stack>#include <queue>#include <cstdlib>#include <algorithm>#include <fstream>#include <ctime>#include <set>using namespace std;#define inf 0x3f3f3f3f#define ll long long#define N 2000005struct node{    int a,b,p,st;//数,个数,分值,状态}num[1005];struct Ys//约数  {      int num,len;      int ys[N];      int cnt[N];  }temp; int n,k;int np[4];int isprime[N];int prime[N],sum;bool cmp(node a,node b){    return a.p>b.p;}void initisprime()//判断素数{    int i,j;    for(i=2;i<N;i++)isprime[i]=1;    for(i=2;i<N;i++)    {        for(j=2;i*j<N;j++)            isprime[i*j]=0;    }}void initprime()//筛选素数{    int i,j,flag;      prime[0]=2;      sum=1;      for(i=3;i<N;i++)      {          flag=1;          for(j=0;j<sum&&prime[j]*prime[j]<=i;j++)          {              if(i%prime[j]==0)              {                  flag=0;break;              }          }          if(flag)prime[sum++]=i;      }  }void fj(int num)//分解质因数  {      temp.num=num;      temp.len=0;      int i;      for(i=0;i<sum&&prime[i]*prime[i]<=num;i++)      {          if(num%prime[i]==0)          {              temp.ys[temp.len]=prime[i];              temp.cnt[temp.len]=1;              num/=prime[i];              while(num%prime[i]==0)temp.cnt[temp.len]++,num/=prime[i];              temp.len++;          }      }      if(num!=1)      {          temp.ys[temp.len]=num;          temp.cnt[temp.len]=1;          temp.len++;      }  }ll pm(ll x,ll y){    ll ret=1;    while(y--)ret*=x;    return ret;}int getp(int x,int mm){    int ret=0,cntd=1,sumd=0,sumj,i,j,flag,rst=0;    if(isprime[x])rst|=1,ret++;    //第一个条件    fj(x);    if(temp.len==1&&isprime[temp.cnt[0]+1])rst|=2,ret++;    //第二个条件    if(temp.len==1&&isprime[(pm(temp.ys[0],temp.cnt[0]+1)-1)/(temp.ys[0]-1)])rst|=4,ret++;    //第三个条件    flag=1;    for(i=0;i<temp.len;i++)    {        if(!flag)break;        sumj=(temp.cnt[i]+1)*temp.cnt[i]/2;        if(sumj%2==0)continue;        for(j=0;j<temp.len;j++)        {            if(i!=j)            {                if((temp.cnt[j]+1)%2==0)break;            }        }        if(j==temp.len)flag=0;    }    if(flag)rst|=8,ret++;    //第四个条件    num[mm].st=rst;    return ret;}int main(){    initisprime();    initprime();    int t,i,ans,j,temp,re,ti,tt;    scanf("%d",&t);    while(t--)    {        scanf("%d%d",&n,&k);        for(i=0;i<n;i++)scanf("%d%d",&num[i].a,&num[i].b);        for(i=0;i<4;i++)scanf("%d",&np[i]);        for(i=0;i<n;i++)num[i].p=getp(num[i].a,i);        printf("%d",num[0].p);        for(i=1;i<n;i++)printf(" %d",num[i].p);        printf("\n");        sort(num,num+n,cmp);        ans=-inf;        for(i=0;i<16;i++)        {            temp=0;            tt=0;            re=k;            for(j=0;j<n;j++)            {                if((num[j].st&i)==0)                {                    if(re==0)break;                    tt|=num[j].st;                    if(re>=num[j].b)                    {                        temp+=num[j].p*num[j].b;                        re-=num[j].b;                    }                    else                    {                        temp+=num[j].p*re;                        re=0;                    }                    if(re==0)break;                }            }            for(j=0;j<4;j++)            {                if((tt&(1<<j))==0)temp+=np[j];            }            if(re==0)ans=max(ans,temp);        }        printf("%d\n",ans);    }    return 0;}


原创粉丝点击