题意:给一系列操作,每个操作有两个数t和k,t=0表示求k以内的最大反素数;t=1表示求小于k且与k互质的数的个数。

 分析:对第一个操作,直接用dfs求反素数就行了,直接上反素数的模板;第二个操作素数筛法的思想预先打个表。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<queue>
#define maxn 60001
#define inf (1ll<<62)
using namespace std;
long long _,type,k,np[maxn],ans,ca=0;
int p[] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53};
void dfs(int kk,long long num,long long sum,long long limit)
{
    if (sum>k) return ;
    if (sum==k) ans=min(ans,num);
        for (int i=1;i<=limit;i++) {
            if (ans/p[kk] <num || sum*(i+1)>k) break;
            num*=p[kk];
            if (k%(sum*(i+1))==0)
                dfs(kk+1,num,sum*(i+1),i);
        }
}

int main()
{
    scanf("%lld",&_);
    int i,j;
    for (i=0;i<maxn;i++) np[i]=i;
    for (i=1;i<maxn;i++)
    {
        for (j=i;j<maxn;j+=i) np[j]--;
        if (!np[np[i]]) np[np[i]]=i;
        np[i]=0;
     }
    //for (i=1;i<=100;i++) cout<<np[i]<<endl;
    while (_--)
    {
        scanf("%lld%lld",&type,&k);
        if (type==1) ans=np[k]; else
        {
            ans=inf;
            dfs(0,1,1,62);
         }
        printf("Case %lld: ",++ca);
        if (ans==0) puts("Illegal"); else if (ans>=inf) puts("INF"); else
            printf("%lld\n",ans);
     }
    return 0;
 }

 

posted on 2017-01-26 10:11  hnqw1214  阅读(390)  评论(0编辑  收藏  举报