luogu1072 [NOIp2009]Hankson的趣味题 (数学+STL::set)

一个JSB做法

由$\frac{x*b0}{gcd(x,b0)}=b1$,可得$\frac{x}{gcd(x,b0)}=\frac{b1}{b0}$

设$b2=\frac{b1}{b0}$

所以对$b2$和$b0$分解质因数,可以得到结论:

  1.x必须包含b2中所有的质因数,且个数等于它在b2和b0(如果b0中有的话)中的数量和

  2.对于b0中有但b2中没有的质因数,x中它的个数可以是[0,b0中的个数]

然后关于a0和a1,也有结论:

  1.x中必须包含a1中的所有质因数

  2.x中不能包含a0中的、a1以外的(在数量和种类方面)质因数

然后就可以开始乱搞了

首先打出1e5以内的素数,然后拿着它们分解质因数(因为我只需要做到$\sqrt{N}$)。注意一个数如果最后剩下不是1,那么剩下这个数也是个质因数(大于$\sqrt{N}$)

然后把这些存到set里,按照上面的规则乱搞......

一个数最多大概也就十几种质因数,所以复杂度没什么问题。

 1 #include<bits/stdc++.h>
 2 #define pa pair<int,int>
 3 #define IT set<pa>::iterator
 4 #define CLR(a,x) memset(a,x,sizeof(a))
 5 using namespace std;
 6 typedef long long ll;
 7 const int maxn=1e5+10,inf=2e9+1;
 8 
 9 inline ll rd(){
10     ll x=0;char c=getchar();int neg=1;
11     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
12     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
13     return x*neg;
14 }
15 
16 bool ispri[maxn];
17 int pri[maxn],pct;
18 set<pa> g[5];
19 
20 inline void get(int id,int x){
21     g[id].clear();
22     for(int i=1;x>1&&i<=pct;i++){
23         if(x<pri[i]) break;
24         if(x%pri[i]) continue;
25         int cnt=0;
26         while(x%pri[i]==0) x/=pri[i],cnt++;
27         g[id].insert(make_pair(pri[i],cnt));
28     }
29     if(x!=1) g[id].insert(make_pair(x,1));
30     
31 }
32 
33 int main(){
34     int i,j;
35     int N=rd();
36     CLR(ispri,1);ispri[0]=ispri[1]=0;
37     for(i=2;i<=100000;i++){
38         if(ispri[i]){
39             for(j=i+i;j<=100000;j+=i){
40                 ispri[j]=0;
41             }
42         }
43     }for(i=2,j=0;i<=100000;i++) if(ispri[i]) pri[++pct]=i;
44     for(i=1;i<=N;i++){
45         int a1=rd(),a2=rd(),b1=rd(),b2=rd();
46         int b3=b2/b1;
47         get(0,a1);get(1,a2);get(2,b1);get(3,b3);
48         g[4].clear();
49         for(IT it=g[0].begin();it!=g[0].end();it++){
50             IT it2=g[1].lower_bound(make_pair(it->first,-1));
51             if(it2->first!=it->first) g[4].insert(make_pair(it->first,0));
52             else if(it2->second!=it->second) g[4].insert(make_pair(it->first,it2->second));
53             else g[4].insert(make_pair(it->first,-it2->second));
54         }
55         int ans=1;
56         for(IT it=g[4].begin();it!=g[4].end();it++){
57             IT it2=g[2].lower_bound(make_pair(it->first,-inf));
58             IT it3=g[3].lower_bound(make_pair(it->first,-inf));
59             if(it->second&&it2->first!=it->first&&it3->first!=it->first) ans=0;
60             if(it->first==it3->first&&it2->first!=it->first&&((it->second>=0&&it3->second!=it->second)||(it->second<0&&(-it->second)>it3->second))) ans=0; 
61         }
62         if(!ans) {printf("0\n");continue;}
63         for(IT it=g[2].begin();it!=g[2].end()&&ans;it++){
64             IT it2=g[3].lower_bound(make_pair(it->first,-inf));
65             IT it3=g[4].lower_bound(make_pair(it->first,-inf));
66             if(it2->first!=it->first){
67                 if(it3->first!=it->first) ans*=it->second+1;
68                 else if(abs(it3->second)>it->second) ans=0;
69                 else if(it3->second<0) ans*=it->second+it3->second+1;
70             }else{
71                 if(it3->first!=it->first);
72                 else if(it3->second>=0&&it3->second!=it2->second+it->second) ans=0;
73                 else if(it3->second<0&&it2->second+it->second<-it3->second) ans=0;
74             }
75         }
76         printf("%d\n",ans);
77     }
78     return 0;
79 }

 

posted @ 2018-10-13 11:01  Ressed  阅读(161)  评论(0编辑  收藏  举报