时间:2016-04-21 16:45:58 星期四
题目编号:[2016-04-21]LightOJ][1341][Aladdin and the Flying Carpet]
题目大意:
- 给定数a,b,问满足c×d==a且b⩽c,b⩽d 二元组对数,
- (c,d)和(d,c)是同种情况
- c != d
分析:
- 分解a(唯一分解定理),n=pa11+pa22+…+paii+pann
- 求约数的个数 cnt=(a1+1)(a2+1)…(ai+1)…(an+1)
- 因为不考虑c == d的情况,所以直接总的对数直接 n /= 2即可
#include<cstdio>#include<cstring>using namespace std;const int maxn = 1E6 + 10;int pri[maxn + 1];void getPri(){ memset(pri,0,sizeof(pri)); for(int i = 2 ; i <= maxn ; ++i){ if(!pri[i]) pri[++pri[0]] = i; for(int j = 1 ; j <= pri[0] && pri[j] <= maxn/i;++j){ pri[pri[j]*i] = 1; if(i % pri[j] == 0) break; } }}long long fac[maxn][2];int fatcnt;int getFac(long long x){ fatcnt = 0; long long tmp = x; for(int i = 1 ; pri[i] <= tmp/pri[i];++i){ fac[fatcnt][1] = 0; if(tmp % pri[i] == 0){ fac[fatcnt][0] = pri[i]; while(tmp % pri[i] == 0){ ++fac[fatcnt][1]; tmp /= pri[i]; } ++fatcnt; } } if(tmp != 1){ fac[fatcnt][0] = tmp; fac[fatcnt++][1] = 1; } return fatcnt;}int main(){ int t,cntcase = 0; scanf("%d",&t); getPri(); while(t--){ long long a,b; scanf("%lld%lld",&a,&b); if(a < b*b){ printf("Case %d: %d\n",++cntcase,0); continue; } getFac(a); int cnt = 1; for(int i = 0; i < fatcnt ; ++i){ cnt *= (fac[i][1]+1); } cnt /= 2; for(int i = 1; i < b ; ++i){ if(a % i == 0) --cnt; } printf("Case %d: %d\n",++cntcase,cnt); } return 0;}