小明系列故事——未知剩余系
Time Limit: 500/200 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 594 Accepted Submission(s): 123
Problem Description “今有物不知其数,三三数之有二,五五数之有三,七七数之有二,问物几何?”
这个简单的谜题就是中国剩余定理的来历。
在艰难地弄懂了这个定理之后,小明开始设计一些复杂的同余方程组X mod ai = bi 来调戏别人,结果是必然的,都失败了。
可是在这个过程中,小明发现有时并不一定要把ai和bi告诉你。他只需要告诉你,ai在区间 [1, X] 范围内每个值取一次时,有K个ai使bi等于0,或有K个ai使bi不等于0,最小的X就可以求出来了。
你来试试看吧!
Input 输入第一行为T,表示有T组测试数据。
每组数据包含两个整数Type和K,表示小明给出的条件。Type为0表示“有K个ai使bi等于0”,为1表示“有K个ai使bi不等于0”。
[Technical Specification]
1. 1 <= T <= 477
2. 1 <= K <= 47777, Type = 0 | 1
Output 对每组数据,先输出为第几组数据,如果没有这样的数,输出“Illegal”,否则输出满足条件的最小的X,如果答案大于2^62, 则输出“INF”。
Sample Input 3 0 3 1 3 0 10
Sample Output Case 1: 4 Case 2: 5 Case 3: 48
Source
2013腾讯编程马拉松复赛第三场(3月31日)
Recommend liuyiding
题目可以分成两个问题:
1)Type==0 , 求有N个约数的最小正整数X;
2) Type==1, 求有X-N个约数的最小正整数X
对于Type==0.
可以参考CF上的一个题目:http://codeforces.com/problemset/problem/27/E
一个正整数n=p1^a[1] * p2*a[2] …..pt*a[t] 那么它的约数个数就是(1+a[1])*(1+a[2])*……*(1+a[t])
那么如果给定N,有N个约数,那么只要把N进行分解。
进行dfs
对于Type==1
设有x个约数,那么相当于x+N的约数个数就是x.
x+N的约数个数的不大于2*sqrt(x+N)
x<=2*sqrt(x+N)
x*x<=4*(x+N)
这样枚举x就可以求解了。
#include <stdio.h> #include <iostream> #include <string.h> #include <algorithm> using namespace std; //******************************* //素数筛选 const int MAXN=100000; int prime[MAXN+1];//得到小于等于MAXN的所有素数 void getPrime() { memset(prime,0,sizeof(prime)); for(int i=2;i<=MAXN;i++) { if(!prime[i])prime[++prime[0]]=i; for(int j=1;j<=prime[0]&&prime[j]<=MAXN/i;j++) { prime[prime[j]*i]=1; if(i%prime[j]==0)break; } } } /* *合数分解(前面需要先素数筛选) */ long long factor[100][2]; int fatCnt; int getFactors(long long x) { fatCnt=0; long long tmp=x; for(int i=1;prime[i]<=tmp/prime[i];i++) { factor[fatCnt][1]=0; if(tmp%prime[i]==0) { factor[fatCnt][0]=prime[i]; while(tmp%prime[i]==0) { factor[fatCnt][1]++; tmp/=prime[i]; } fatCnt++; } } if(tmp!=1) { factor[fatCnt][0]=tmp; factor[fatCnt++][1]=1; } return fatCnt; } /* ************************** */ const long long INF=(1LL<<62)+1; int N; long long ans; long long a[47787]; void dfs(int i,long long x,int n) { if(n>47777)return; if(x<INF && (a[n]==0||a[n]>x))a[n]=x; for(int j=1;j<=62;j++) { if(INF/prime[i]<x)break; x*=prime[i]; if(x>=INF)break; dfs(i+1,x,n*(j+1)); } } int get(int x)//得到x的约数个数 { getFactors(x); int ans=1; for(int i=0;i<fatCnt;i++) ans*=(factor[i][1]+1); return ans; } void solve2() { int x=2; while(x*x<=4*(N+x)) { if(x==get(N+x)) { printf("%d\n",N+x); return; } x++; } printf("Illegal\n"); } void init() { memset(a,0,sizeof(a)); dfs(1,1,1); } int main() { int T; getPrime(); int iCase=0; scanf("%d",&T); int Type; init(); while(T--) { iCase++; scanf("%d%d",&Type,&N); printf("Case %d: ",iCase); if(Type==0) { if(a[N]!=0)printf("%I64d\n",a[N]); else printf("INF\n"); } else solve2(); } return 0; }