@xiaoziyao
        
        2021-03-22T05:41:50.000000Z
        字数 3516
        阅读 1505
    解题报告
P4930 [PA2013]Euler解题报告:
组数据,给定,求的所有。()
原来的题目数据有锅,修完数据后拿到了首杀。
搜索题。
首先求出的所有因子计入,然后把所有中为质数的值存入,不难发现很小,也很小,随便交几发讨论一下就可以知道最大是,最大是。
记为数字在质因数中的排名,但由于这里可能存不下,因此考虑对于的大小讨论:如果则将的排名存入,否则将的排名存入,这样就只需要开的数组了。
然后就开始玄学起来了。
设代表中第一个是因子的数的编号,(如果不存在则为)
这里介绍一个众所周知的结论:对于,满足(下面有证明)。
然后进行搜索:表示现在搜索到第个了,将除到了(这个为值),并把答案乘到了,边界就是的时候直接把放入答案。
不难发现一定在里(可以通过和找到),因此我们可以通过跳过那些不能整除的。
然后再分类讨论就好了:
复杂度很玄学,但跑的很稳。
记得特判,还有有些地方需要排序。
#include<stdio.h>#include<algorithm>#define int long longusing namespace std;const int maxn=1000005,maxm=2505,maxk=700;int T,n,cnt,m,Ps,Ds,anss;int p[maxn],a[maxn],P[maxk],D[maxm],ans[maxn],ord[maxn],nord[maxn],f[maxm][maxk];void sieve(int n){for(int i=2;i<=n;i++){if(p[i]==0)a[++cnt]=i;for(int j=1;j<=cnt;j++){if(i*a[j]>n)break;p[i*a[j]]=1;if(i%a[j]==0)break;}}}int check(int x){if(x<=1000000)return p[x]==0;for(int i=2;i*i<=x;i++)if(x%i==0)return 0;return 1;}void dfs(int pos,int val,int now){if(now==1){ans[++anss]=val;return ;}if(now<=m)pos=f[ord[now]][pos];else pos=f[nord[n/now]][pos];if(pos==Ps+1)return ;dfs(pos+1,val,now);val*=P[pos],now/=P[pos]-1,dfs(pos+1,val,now);while(now%P[pos]==0)val*=P[pos],now/=P[pos],dfs(pos+1,val,now);}signed main(){scanf("%lld",&T),sieve(1000000);while(T--){scanf("%lld",&n);if(n==1){puts("2\n1 2");continue;}for(m=1;1ll*(m+1)*(m+1)<=n;m++);for(int i=1;i<=m;i++)if(n%i==0){D[++Ds]=i;if(check(i+1))P[++Ps]=i+1;if(1ll*i*i!=n){D[++Ds]=n/i;if(check(n/i+1))P[++Ps]=n/i+1;}}sort(P+1,P+1+Ps),sort(D+1,D+1+Ds);for(int i=1;i<=Ds;i++){if(D[i]<=m)ord[D[i]]=i;else nord[n/D[i]]=i;f[i][Ps+1]=Ps+1;for(int j=Ps;j>=0;j--)f[i][j]=D[i]%(P[j]-1)==0? j:f[i][j+1];}dfs(1,1,n),sort(ans+1,ans+1+anss);printf("%lld\n",anss);for(int i=1;i<=anss;i++)printf("%lld%c",ans[i],i==anss? '\n':' ');if(anss==0)puts("");for(int i=1;i<=Ds;i++){if(D[i]<=m)ord[D[i]]=0;else nord[n/D[i]]=0;}anss=Ds=Ps=0;}return 0;}
这里有一份时代久远的关于上面式子的证明:
引理:欧拉函数的积性
构造一个()的矩阵:
易知每一行都是m的完全剩余系,那么对于所有,都有。
因此有。
也很容易证明每一列都是的完全剩余系。
反证法:设与模同余,且,那么。
也就是。
两式相减得。
又因为,所以那么不难发现,所以每一列都是的完全剩余系。
由欧拉函数的定义得矩阵内可以找到列,其中有个元素同时与m和n互素,即共个元素与和互素,也就是与互素。
然后证明欧拉函数的公式:对于,满足。
首先很显然为质数的时候,。
然后是时(为质数,):
很容易证明,与等价,那么可以发现与不互素的数只有这个数。
那么。
当为任意正整数时,设,由的积性可知。