bzoj3737 [Pa2013]Euler

https://www.lydsy.com/JudgeOnline/problem.php?id=3737

https://szkopul.edu.pl/problemset/problem/5LCCf9uDmKEBYhuzP7iT-8SM/site/?key=statement

根据欧拉函数那个式子,设a分解质因数后为a1^p1*a2^p2*..*ak^pk,a的欧拉函数就等于(a1-1)*a1^(p1-1)*(a2-1)*a2^(p2-1)*..*(ak-1)*ak^(pk-1)

那么,暴力枚举给出n的所有因子,将它们全部+1,然后只保留它们中的质数,那么x的质因子只可能在这些质数中产生

这样的质数不多,爆搜就好了。。。当然如果n是1要特判一下,直接输出1和2

好吧,直接爆搜会T飞。。。

我在网上找到了解决方法:

设当前还要构造出的欧拉函数值为nowphi,如果还要拆成两个或以上个数的积,那么其中最小数一定<=sqrt(nowphi);如果当前要考虑的最小的质数-1(是最小的可能的因子)也>sqrt(nowphi),那么自然不可能拆成两个或以上的个数的积

现在唯一可能是nowphi单独作为一项存在;要求是,nowphi+1>=当前考虑质数(不然在其他情况会考虑到),且nowphi+1是质数

这是一个大剪枝,可以A了。。。貌似复杂度还是有保证的?https://www.bbsmax.com/A/B0zq67P8Jv/

讲不清楚。。。

扫描二维码关注公众号,回复: 2947414 查看本文章
  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<vector>
  5 #include<map>
  6 #include<cmath>
  7 using namespace std;
  8 #define fi first
  9 #define se second
 10 #define mp make_pair
 11 #define pb push_back
 12 typedef long long ll;
 13 typedef unsigned long long ull;
 14 typedef pair<ll,ll> pii;
 15 
 16 namespace M
 17 {
 18 //不会...板子先贴过来
 19 const ll prime[] = {2, 3, 7, 61, 24251};
 20 const ll MT = 5;
 21 inline ll mulmod(ll x, ll y, ll mod)
 22 {
 23     ll tmp=(x*y-ll((long double)x/mod*y+1.0e-8)*mod);
 24     return tmp<0?tmp+mod:tmp;
 25 }
 26 inline ll powermod(ll a, ll b, ll k)
 27 {
 28     ll re = 1, temp = a;
 29     while (b)
 30     {
 31         if (b & 1)
 32             re = mulmod(re, temp, k);
 33         temp = mulmod(temp, temp, k);
 34         b >>= 1;
 35     }
 36     return re;
 37 }
 38 ll TwiceDetect(ll a, ll b, ll k)
 39 {
 40     ll t = 0;
 41     ll x, y;
 42     while ((b & 1) == 0)
 43     {
 44         b >>= 1;
 45         t++;
 46     }
 47     y = x = powermod(a, b, k);
 48     while (t--)
 49     {
 50         y = mulmod(x, x, k);
 51         if (y == 1 && x != 1 && x != k - 1)
 52             return 0;
 53         x = y;
 54     }
 55     return y;
 56 }
 57 bool Miller_Rabin(ll n)
 58 {
 59     ll i;
 60     ll tmp;
 61     for (i = 0; i < MT; i++)
 62     {
 63         tmp = prime[i];
 64         if (n == prime[i])
 65             return true;
 66         if (TwiceDetect(tmp, n - 1, n) != 1)
 67             break;
 68     }
 69     return (i == MT);
 70 }
 71 }
 72 using M::Miller_Rabin;
 73 
 74 const ll N=1000000;
 75 bool nprime[1001000];
 76 ll prime[201000],len;
 77 bool isprime(ll x)
 78 {
 79     if(x>N)  return Miller_Rabin(x);
 80     else    return !nprime[x];
 81 }
 82 
 83 ll T;
 84 ll n;
 85 ll tt[1001],tp;
 86 ll an[1010100],tpa;
 87 void dfs(ll p,ll now,ll nowphi)
 88 {
 89     if(nowphi==1)
 90     {
 91         an[++tpa]=now;
 92         return;
 93     }
 94     if(p>tp) return;
 95     if(tt[p]-1>sqrt(nowphi))
 96     {
 97         if(nowphi+1>=tt[p]&&isprime(nowphi+1))
 98             an[++tpa]=now*(nowphi+1);
 99         return;
100     }
101     dfs(p+1,now,nowphi);
102     if((long double)now*tt[p]>=1e18) return;
103     now*=tt[p];
104     if(nowphi%(tt[p]-1)!=0) return;
105     nowphi/=(tt[p]-1);
106     dfs(p+1,now,nowphi);
107     while(1)
108     {
109         if((long double)now*tt[p]>=1e18) return;
110         now*=tt[p];
111         if(nowphi%tt[p]!=0) return;
112         nowphi/=tt[p];
113         dfs(p+1,now,nowphi);
114     }
115 }
116 int main()
117 {
118     //freopen("/tmp/3737/7.in","r",stdin);
119     //freopen("/tmp/3737/7.ans","w",stdout);
120     ll i,j,ed;
121     nprime[1]=1;
122     for(i=2;i<=N;i++)
123     {
124         if(!nprime[i])  prime[++len]=i;
125         for(j=1;j<=len&&i*prime[j]<=N;j++)
126         {
127             nprime[i*prime[j]]=1;
128             if(i%prime[j]==0)   break;
129         }
130     }
131     scanf("%lld",&T);
132     while(T--)
133     {
134         scanf("%lld",&n);
135         if(n==1)
136         {
137             puts("2");
138             puts("1 2");
139             continue;
140         }
141         tp=0;
142         ed=sqrt(n+0.5);
143         for(i=1;i<=ed;i++)
144             if(n%i==0)
145             {
146                 if(isprime(i+1))    tt[++tp]=i+1;
147                 if(ll(i)*i!=n&&isprime(n/i+1))  tt[++tp]=n/i+1;
148             }
149         sort(tt+1,tt+tp+1);
150         tpa=0;dfs(1,1,n);
151         sort(an+1,an+tpa+1);
152         printf("%lld\n",tpa);
153         for(i=1;i<=tpa;i++)  printf("%lld%c",an[i]," \n"[i==tpa]);
154         if(!tpa)    puts("");
155     }
156     return 0;
157 }

耶,卡到第一了!

卡常版代码:

  1 #pragma GCC optimize(3)
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<vector>
  6 #include<map>
  7 #include<cmath>
  8 using namespace std;
  9 #define fi first
 10 #define se second
 11 #define mp make_pair
 12 #define pb push_back
 13 typedef long long ll;
 14 typedef unsigned long long ull;
 15  
 16 namespace M
 17 {
 18 //不会...板子先贴过来
 19 const ll prime[] = {2, 3, 7, 61, 24251};
 20 const ll MT = 5;
 21 inline ll mulmod(ll x, ll y, ll mod)
 22 {
 23     ll tmp=(x*y-ll((long double)x/mod*y+1.0e-8)*mod);
 24     return tmp<0?tmp+mod:tmp;
 25 }
 26 inline ll powermod(ll a, ll b, ll k)
 27 {
 28     ll re = 1, temp = a;
 29     while (b)
 30     {
 31         if (b & 1)
 32             re = mulmod(re, temp, k);
 33         temp = mulmod(temp, temp, k);
 34         b >>= 1;
 35     }
 36     return re;
 37 }
 38 ll TwiceDetect(ll a, ll b, ll k)
 39 {
 40     ll t = 0;
 41     ll x, y;
 42     while ((b & 1) == 0)
 43     {
 44         b >>= 1;
 45         t++;
 46     }
 47     y = x = powermod(a, b, k);
 48     while (t--)
 49     {
 50         y = mulmod(x, x, k);
 51         if (y == 1 && x != 1 && x != k - 1)
 52             return 0;
 53         x = y;
 54     }
 55     return y;
 56 }
 57 bool Miller_Rabin(ll n)
 58 {
 59     ll i;
 60     ll tmp;
 61     for (i = 0; i < MT; i++)
 62     {
 63         tmp = prime[i];
 64         if (n == prime[i])
 65             return true;
 66         if (TwiceDetect(tmp, n - 1, n) != 1)
 67             break;
 68     }
 69     return (i == MT);
 70 }
 71 }
 72 using M::Miller_Rabin;
 73  
 74 const ll N=500000;
 75 bool nprime[501000];
 76 ll prime[200100],len;
 77 bool isprime(ll x)
 78 {
 79     return x>N?Miller_Rabin(x):!nprime[x];
 80 }
 81  
 82 ll tt[1001],*tp=tt;
 83 ll an[1010100],*tpa=an;
 84 ll now,nowphi;
 85 void dfs(ll *p,ll now,ll nowphi)
 86 {
 87     if(nowphi==1)
 88     {
 89         *(++tpa)=now;
 90         return;
 91     }
 92     if(p>tp) return;
 93     if(*p-1>sqrt(nowphi))
 94     {
 95         if(nowphi+1>=*p&&isprime(nowphi+1))
 96             *(++tpa)=now*(nowphi+1);
 97         return;
 98     }
 99     dfs(p+1,now,nowphi);
100     //if((long double)now*(*p)>=1e18)    return;
101     now*=(*p);
102     if(nowphi%((*p)-1)!=0) return;
103     nowphi/=((*p)-1);
104     dfs(p+1,now,nowphi);
105     while(1)
106     {
107         //if((long double)now*(*p)>=1e18)    return;
108         now*=(*p);
109         if(nowphi%(*p)!=0)  return;
110         nowphi/=(*p);
111         dfs(p+1,now,nowphi);
112     }
113 }
114 int T;
115 ll n;
116 int main()
117 {
118     //freopen("/tmp/3737/18.in","r",stdin);
119     //freopen("/tmp/3737/18.ans","w",stdout);
120     int i,j,ed;
121     nprime[1]=1;
122     for(i=2;i<=N;i++)
123     {
124         if(!nprime[i])  prime[++len]=i;
125         for(j=1;j<=len&&i*prime[j]<=N;j++)
126         {
127             nprime[i*prime[j]]=1;
128             if(i%prime[j]==0)   break;
129         }
130     }
131     scanf("%d",&T);
132     while(T--)
133     {
134         scanf("%lld",&n);
135         if(n==1)
136         {
137             puts("2");
138             puts("1 2");
139             continue;
140         }
141         tp=tt;
142         ed=sqrt(n+0.5);
143         for(i=1;i<=ed;i++)
144             if(n%i==0)
145             {
146                 if(isprime(i+1))    *(++tp)=i+1;
147                 if(ll(i)*i!=n&&isprime(n/i+1))  *(++tp)=n/i+1;
148             }
149         sort(tt+1,tp+1);
150         tpa=an;dfs(tt+1,1,n);
151         sort(an+1,tpa+1);
152         int ttttt=tpa-an;
153         printf("%d\n",ttttt);
154         for(i=1;i<=ttttt;i++)  printf("%lld%c",an[i]," \n"[i==ttttt]);
155         if(!ttttt)    puts("");
156     }
157     return 0;
158 }
View Code

https://www.luogu.org/problemnew/show/P4780

减弱版?

  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<vector>
  5 #include<map>
  6 #include<cmath>
  7 using namespace std;
  8 #define fi first
  9 #define se second
 10 #define mp make_pair
 11 #define pb push_back
 12 typedef long long ll;
 13 typedef unsigned long long ull;
 14 typedef pair<ll,ll> pii;
 15 
 16 namespace M
 17 {
 18 //不会...板子先贴过来
 19 const ll prime[] = {2, 3, 7, 61, 24251};
 20 const ll MT = 5;
 21 inline ll mulmod(ll x, ll y, ll mod)
 22 {
 23     ll tmp=(x*y-ll((long double)x/mod*y+1.0e-8)*mod);
 24     return tmp<0?tmp+mod:tmp;
 25 }
 26 inline ll powermod(ll a, ll b, ll k)
 27 {
 28     ll re = 1, temp = a;
 29     while (b)
 30     {
 31         if (b & 1)
 32             re = mulmod(re, temp, k);
 33         temp = mulmod(temp, temp, k);
 34         b >>= 1;
 35     }
 36     return re;
 37 }
 38 ll TwiceDetect(ll a, ll b, ll k)
 39 {
 40     ll t = 0;
 41     ll x, y;
 42     while ((b & 1) == 0)
 43     {
 44         b >>= 1;
 45         t++;
 46     }
 47     y = x = powermod(a, b, k);
 48     while (t--)
 49     {
 50         y = mulmod(x, x, k);
 51         if (y == 1 && x != 1 && x != k - 1)
 52             return 0;
 53         x = y;
 54     }
 55     return y;
 56 }
 57 bool Miller_Rabin(ll n)
 58 {
 59     ll i;
 60     ll tmp;
 61     for (i = 0; i < MT; i++)
 62     {
 63         tmp = prime[i];
 64         if (n == prime[i])
 65             return true;
 66         if (TwiceDetect(tmp, n - 1, n) != 1)
 67             break;
 68     }
 69     return (i == MT);
 70 }
 71 }
 72 using M::Miller_Rabin;
 73 
 74 const ll N=1000000;
 75 bool nprime[1001000];
 76 ll prime[201000],len;
 77 bool isprime(ll x)
 78 {
 79     if(x>N)  return Miller_Rabin(x);
 80     else    return !nprime[x];
 81 }
 82 
 83 ll T;
 84 ll n;
 85 ll tt[1001],tp;
 86 ll an=0x3f3f3f3f3f3f3f3f;
 87 void dfs(ll p,ll now,ll nowphi)
 88 {
 89     if(nowphi==1)
 90     {
 91         an=min(an,now);
 92         return;
 93     }
 94     if(p>tp) return;
 95     if(tt[p]-1>sqrt(nowphi))
 96     {
 97         if(nowphi+1>=tt[p]&&isprime(nowphi+1))
 98             an=min(an,now*(nowphi+1));
 99         return;
100     }
101     dfs(p+1,now,nowphi);
102     if((long double)now*tt[p]>2147483648) return;
103     now*=tt[p];
104     if(nowphi%(tt[p]-1)!=0) return;
105     nowphi/=(tt[p]-1);
106     dfs(p+1,now,nowphi);
107     while(1)
108     {
109         if((long double)now*tt[p]>2147483648) return;
110         now*=tt[p];
111         if(nowphi%tt[p]!=0) return;
112         nowphi/=tt[p];
113         dfs(p+1,now,nowphi);
114     }
115 }
116 int main()
117 {
118     //freopen("/tmp/3737/7.in","r",stdin);
119     //freopen("/tmp/3737/7.ans","w",stdout);
120     ll i,j,ed;
121     nprime[1]=1;
122     for(i=2;i<=N;i++)
123     {
124         if(!nprime[i])  prime[++len]=i;
125         for(j=1;j<=len&&i*prime[j]<=N;j++)
126         {
127             nprime[i*prime[j]]=1;
128             if(i%prime[j]==0)   break;
129         }
130     }
131     scanf("%lld",&n);
132     if(n==1)
133     {
134         puts("1");
135         return 0;
136     }
137     tp=0;
138     ed=sqrt(n+0.5);
139     for(i=1;i<=ed;i++)
140         if(n%i==0)
141         {
142             if(isprime(i+1))    tt[++tp]=i+1;
143             if(ll(i)*i!=n&&isprime(n/i+1))  tt[++tp]=n/i+1;
144         }
145     sort(tt+1,tt+tp+1);
146     dfs(1,1,n);
147     if(an<2147483648)    printf("%lld",an);
148     else    printf("%d",-1);
149     return 0;
150 }
View Code

猜你喜欢

转载自www.cnblogs.com/hehe54321/p/9556479.html