羅区P1072 Hankson興味深い質問
JDOJ 1648:[NOIP2009] Hankson興味深い質問T2
説明
博士ハンクスは、よく知られた専門家のBT(バイオテック、バイオ)フィールドであり、彼の息子がHanksonの名前。今、ちょうど家学校Hanksonから我々は興味深い質問を考えています。
今日、教室で、教師はどのように2つの正の整数の合計はC1とC2最大公約数と最小公倍数を説明します。あなたはこの知識をマスターした今Hanksonが思うに、彼は「追求公約数」と考えるようになった「逆問題」の質問のように「一般的な複数の追求」、質問はこれです:正の整数A0を考えると、A1、B0、 B1、未知を満たす正の整数Xを提供:
1。xはA1 A0最大公約数である;
2。B0は、xとB1の最小公倍数です。
「逆問題」のHanksonは、正の整数xの条件を満たしていると判断されます。しかし、少し考えた後、彼はそのようなxが存在さえしないかもしれない、一意ではないことがわかりました。そこで彼は、xの条件を満たすように番号を解決する方法について考え始めるためになりました。彼はプログラミングの問題を解決するのに役立ちます。
入力
最初の入力ファイルの正の整数n、入力データのnのセットを行います。次のn行スペースで区切られた各二つの整数の間で入力データは、4つの正の整数のA0、A1、B0、B1、の組のそれぞれ。入力データa1 A0は割り切れていることを確認するには、B1、B0は割り切れ。
出力
出力ファイルの合計n行目。ライン当たり各入力データの出力は、整数です。
各試験のために、Xが存在する場合、出力0;
このxが存在する場合、番号Xの出力が条件を満たし。
サンプル入力
2 41 1 96 288 95 1 37 1776
サンプル出力
6 2
ヒント
[説明]
入力データの最初のセットは、xは9,18,36,72,144,288、6の合計であってもよいです。
入力データの第2セットは、xが48,1776、両者の合計であってもよいです。
[データ]の範囲
のデータの50%、1≤a0、A1、B0、b1≤10000とn≤100を確保するため。
データの100%に、1≤a0、A1、B0、b1≤2,000,000,000とn≤2000を確保します。
ソース
ソリューション:
- 暴力は試すことができます
最初の50ポイントのデータ範囲を参照する最初の試みは、あなたが50ptsの上に裸の暴力を使用することができます。
コード:
#include<cstdio>
#include<algorithm>
using namespace std;
int n,ans;
int a,a1,b,b1;
int gcd(int x,int y)
{
return y?gcd(y,x%y):x;
}
int lcm(int x,int y)
{
return (x*y)/gcd(x,y);
}
int main()
{
scanf("%d",&n);
while(n--)
{
ans=0;
scanf("%d%d%d%d",&a,&a1,&b,&b1);
for(int i=1;i<=max(a,b1);i++)
if(gcd(i,a)==a1 && lcm(i,b)==b1)
ans++;
printf("%d\n",ans);
}
return 0;
}
- 暴力の最適化
その後、この暴力が完全に、わずかな数学的な控除を最適化することができ、自身が愚かが見つかりました:第2の条件\(LCM(Iを、B)= B_1 \) 、我々はそれが条件を満たしていた私は\(\ )しなければならない(B_1 \)\数字については、それは取り扱いが容易で、\(B_1 \)行の数についての判断で暴力を実行し、すべてを処理するの数について。
いくつかのスクリーニングについての知識としては、以下のブログを参照してください。
:(だから、同様裸の暴力のケースを開けない可能性があります、長い長い開くには、次のコードを持っています私が知っているか聞いてはいけません)
60〜70は、実際100は、(?? !!)、期待されています
#include<cstdio>
#define ll long long
using namespace std;
ll n,ans;
ll a,b,c,d;
inline int gcd(int x,int y)
{
return y?gcd(y,x%y):x;
}
inline ll lcm(int x,int y)
{
return (ll)x*(ll)y/(ll)gcd(x,y);
}
int main()
{
scanf("%lld",&n);
while(n--)
{
ans=0;
scanf("%lld%lld%lld%lld",&a,&b,&c,&d);
for(int i=1;i*i<=d;i++)
{
if(d%i==0)
{
if(gcd(a,i)==b && lcm(c,i)==d)
ans++;
if(i!=d/i)
{
if(gcd(d/i,a)==b && lcm(d/i,c)==d)
ans++;
}
}
}
printf("%d\n",ans);
}
return 0;
}