1160: Confusion in the Problemset
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 107 Solved: 15
[ Submit][ Status][ Web Board]
Description
You are in an m x n grid. You are standing in position (0, 0) and in each of the other lattice points (points with integer co-ordinates) an enemy is waiting. Now you have a ray gun that can fire up to infinity and no obstacle can stop it. Your target is to kill all the enemies. You have to find the minimum number of times you have to fire to kill all of them. For a 4 x 4 grid you have to fire 13 times. See the picture below:
Input
Input starts with an integer T (≤ 100), denoting the number of test cases.
Each case contains two integers m, n (0 ≤ m, n ≤ 109) and at least one of them will be less than or equal to 106.
Output
For each case, print the case number and the minimum number of times you have to fire to kill all the enemies.
Sample Input
Sample Output
HINT
Source
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long lld;
const int maxn=1000005;
bool mk[maxn];
int f[maxn];
int p[maxn];
int a[maxn];
void Gao()
{
int i,j;
for(i=1;i<maxn;i++)
{
p[i]=1; mk[i]=0;
}
for(i=2;i<maxn;i++)
if(!mk[i])
{
p[i]=f[i]=i;
for(j=i*2;j<maxn;j+=i)
{
f[j]=i;//记录j的最大质因子i
mk[j]=1;
p[j]*=i;//质因子的积
}
}
}
int main()
{
int T;
int cas=1,num,n,m;
int i,j,k;
int fact[15];
lld ans;
Gao();
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
if(n>m) n^=m^=n^=m;
if(n==0 ||m==0)
{
printf("Case %d: %d\n",cas++,(m^n)!=0);
continue ;
}
ans=2;
for(i=1;i<=n;i++)
{
if(i==p[i])
{
a[i]=num=0;
for(j=i;j!=1;j/=f[j])//求i的质因子
fact[num++]=f[j];
for(j=0;j<(1<<num);j++)//容斥原理
{
int tmp=1,sign=1;
for(k=0;k<num;k++)
if(j&(1<<k))
{
tmp*=fact[k];
sign=-sign;
}
a[i]+=m/tmp*sign;
}
}
ans+=a[p[i]];
}
printf("Case %d: %lld\n",cas++,ans);
}
return 0;
}
标程
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct point
{
int x,cnt;
friend bool operator<(const point &p,const point &q){
return p.x<q.x;
}
}c[1000010];
int a[1100010],pri[1100010];
void prime()
{
memset(a,0,sizeof(a));
int i,j;
for(i=2;i*i<=1100000;i++)
if(!a[i])
for(j=i*i;j<=1100000;j+=i)
a[j]=1;
for(i=0,j=2;j<=1100000;j++)
if(!a[j]) pri[i++]=j;
}
int cnt=0;
void dfs(int mul,int pos,int step)
{
c[cnt].cnt=step;
c[cnt++].x=mul;
int up=1000000/mul;
for(int i=pos;pri[i]<=up;i++){
dfs(mul*pri[i],i+1,step+1);
}
}
int main()
{
prime();
dfs(1,0,0);
sort(c,c+cnt);
int t;
scanf("%d",&t);
for(int k=1;k<=t;k++){
long long n,m,ans=0;
scanf("%lld%lld",&n,&m);
for(int i=0;i<cnt;i++)
if(c[i].x>min(n,m)) break;
else if(c[i].cnt&1) ans-=(n/c[i].x)*(m/c[i].x);
else ans+=(n/c[i].x)*(m/c[i].x);
if(n==0&&m==0) ans=0;
else if(n==0||m==0) ans=1;
else ans+=2;
printf("Case %d: %lld\n",k,ans);
}
return 0;
}