SGU 537 Divisibility 枚举
2014-07-17 08:52
295 查看
题意:给定一个长度在[1,14],由小写字母组成,不能同字母数至多10个的字符串,每种字母可以任意取数字映射,但不同字母对应的数字不能相同,相同字母对应的数字必须相同(注意:转换的数字不能有前导0)。问给定字符串所有映射数的最大公约数是多少?输出这个最大公约数的所有因子。例如abab可以构成1010,2323,7575等等,最大公约数为101.
题解:
没找到什么特殊的方法,只能暴力下,枚举了所有数字组合,当然这样肯定超时间,所以需要限定枚举次数,这种属于概率型,还是成功了,哈哈。最后的输出达到1e14,所以需要先预处理1e7的素数,然后找出所有质因子,然后用go()函数输出所有因子。
代码:
题解:
没找到什么特殊的方法,只能暴力下,枚举了所有数字组合,当然这样肯定超时间,所以需要限定枚举次数,这种属于概率型,还是成功了,哈哈。最后的输出达到1e14,所以需要先预处理1e7的素数,然后找出所有质因子,然后用go()函数输出所有因子。
代码:
#include <cstdio> #include <cstring> #include <cmath> #include <vector> #include <algorithm> #include <iostream> #include <queue> #include <ctime> #include <cstdlib> using namespace std; #define LL __int64 const int maxn=250; const int maxm=1e6; char a[maxn]; int c[maxn]; int n,m,t,num,tot,k; int prime[maxm],vis[10],d[10],g[10000],gg,f[10000],ff; bool check[10000010]; LL ret[10000],res,ans; LL gcd(LL a,LL b)//求最大公约数 { return b==0?a:gcd(b,a%b); } /*void random(int x) { int i,j,k; x=10; srand((unsigned)time(NULL)); for(i=0;i<x;i++) b[i]=i; m=x; for(i=0;i<x;i++) { int p=rand()%m; while(i==0&&p==0)p=rand()%m; f[i]=b[p]; b[p]=b[m-1]; m--; } for(i=0;i<x;i++) printf("%d ",f[i]); printf("\n"); }*/ void init()//预处理,找出所有1e7以内的素数,以减少查找1e14范围数的因子的时间 { //现行筛素数的方法,时间复杂度为O(n) memset(check,false,sizeof(check)); int i,j; tot=0; for(i=2;i<=1e7;i++) { if(!check[i])prime[tot++]=i; for(j=0;j<tot;j++) { if(i*prime[j]>1e7)break; check[i*prime[j]]=true; if(i%prime[j]==0)break; } } //printf("%d\n",tot); //for(i=0;i<20;i++) // printf("prime[%d]:%d\n",i,prime[i]); } void dfs(int x)//枚举所有字母对应的数字 { if(k>84000)return;//限定次数,概率型水着题目,k值可以取到140000。 if(x==t) { k++; res=0; for(int i=0;i<n;i++) res=res*10+d[c[a[i]-'a']]; ans=gcd(ans,res); return ; } int i,j; for(i=(x==0?1:0);i<10;i++) { if(vis[i])continue; d[x]=i; vis[i]=1; dfs(x+1); if(k>84000)return; vis[i]=0; } } void go(int now,int dep,LL mul)//通过质因子递归枚举所有因子 { if(now==dep) { ret[num++]=mul; return; } for(int i=0;i<=f[now];i++) { go(now+1,dep,mul); mul*=g[now]; } } int main() { init(); int T,tt=0; scanf("%d",&T); LL p,q; while(T--) { int i,j; scanf("%s",a); n=strlen(a); memset(c,-1,sizeof(c)); t=0; for(i=0;i<n;i++) { if(c[a[i]-'a']==-1)c[a[i]-'a']=t++; } //random(t); ans=0; for(i=0;i<n;i++) ans=ans*10+(c[a[i]-'a']+1)%10; memset(vis,0,sizeof(vis)); k=0; dfs(0); //找出所有的质因子以及个数 num=0; gg=0; for(i=0;prime[i]*prime[i]<=ans;i++) { if(ans%prime[i])continue; ff=0; while(ans%prime[i]==0) { ff++; ans=ans/prime[i]; } g[gg]=prime[i]; f[gg]=ff; gg++; } if(ans>1) { g[gg]=ans; f[gg]=1; gg++; } //找出所有因子 go(0,gg,1); //输出 sort(ret,ret+num); printf("Case %d: %I64d",++tt,ret[0]); for(i=1;i<num;i++) if(ret[i]!=ret[i-1]) printf(" %I64d",ret[i]); printf("\n"); } return 0; }
相关文章推荐
- sgu 537 Divisibility
- SGU 537 Divisibility
- SGU 537 Divisibility
- SGU 158 Commuter Train(暴力+枚举)
- sgu 499. Greatest Greatest Common Divisor(枚举因子)
- POJ 1745:Divisibility 枚举某一状态的DP
- SGU - 499 Greatest Greatest Common Divisor 枚举因子(n logn)
- POJ 1745:Divisibility 枚举某一状态的DP
- Codeforces 550C —— Divisibility by Eight——————【枚举 || dp】
- SGU 532 Building Foundation(枚举)
- SGU-499-枚举因子
- SGU 142. Keyword(暴力枚举)
- SGU 148 枚举出奇迹 单调性以及前缀和
- SGU 128. Snake --- 暴力枚举+并查集+贪心+计算几何
- fzu 1912 Divisibility by Thirty-six(数论+枚举)
- CodeForces 550C Divisibility by Eight 数学 枚举
- params ref和out 枚举 面向对象
- 【枚举】_枚举的作用笔记
- 集合框架取出元素的方式(二)Enumeration枚举方式
- 特殊回文数 --枚举