题解 P6452 【[COCI2008-2009#4] TREZOR】
题目大意
给出一个
分析
对于两线之后不经过其他点的点对
设
那么对于第
考虑
同时被两个点看到的方案数
恰好只会被第一个特殊点看到的方案数
代码
#include<bits/stdc++.h>
#define REP(i,first,last) for(int i=first;i<=last;++i)
#define DOW(i,first,last) for(int i=first;i>=last;--i)
using namespace std;
const int PRIME[303]={2,3,5,7,11,13,....};//2000 以内的质数表
int a,b,l;
long long answer1,answer2;
long long sum;
int cnt=0;
int num[100];
void DFS(int now=1,int use=0,long long add=1)
{
if(now==cnt+1)
{
sum+=1ll*(use&1?-1:1)*(l/add);//选了偶数个是加上,选了奇数个是减
return;
}
DFS(now+1,use,add);
DFS(now+1,use+1,add*num[now]);
}
long long Calc(int a)
{
if(!a)
{
return 1;
}
sum=0;
cnt=0;
REP(i,0,302)//将数分解为若干质数的幂次的乘积的形式
{
if(a%PRIME[i]==0)
{
num[++cnt]=PRIME[i];
while(a%PRIME[i]==0)
{
a/=PRIME[i];
}
}
}
if(a^1)
{
num[++cnt]=a;
}
DFS();//暴力 DFS 容斥
return sum;
}
int main()
{
scanf("%d%d%d",&a,&b,&l);
int len=a+b+1;
REP(i,1,len)
{
a=i-1;
b=len-i;
long long ua=Calc(a);//第一个特殊点可以看见的点的数量
long long ub=Calc(b);//第二个特殊点可以看见的点的数量
long long uab=Calc(a*b);//第一个和第二个特殊点可以同时看见的点的数量
answer2+=uab;//记录答案
answer1+=ua-uab+ub-uab;
}
printf("%lld\n%lld\n%lld\n",1ll*len*l-answer1-answer2,answer1,answer2);
return 0;
}