您的位置:首页 > 其它

sgu 537 Divisibility

2013-11-29 12:01 162 查看
题意:

  给你一个字符串,其中的每个字母都可以对应0-9之间的一个数字,且不同的字母不能对应同一个数字,然后就得到了一个数字,求所有这些可能得到的数字的共同约数,最多出现10个不同的字母,字符串长度最大是14。

思路:

  一看题目首先就感觉是暴力,10!大概300+W的复杂度,暴力求出来每一个数然后求它们的gcd,由于10^14比较大,直接枚举因子要10^7,所以先分解质因数,然后再dfs求所有情况。结果果断TLE,这时注意到有100个case,100*300W肯定会TLE啊。赛后看了别人的做法,当存在10个不同的字母时,可以直接特判,这样复杂度就可以降到9!*100,就可以过了!

  后来听杨神说,这种题直接随机就行了...然后就写了一发随机,哎,坑爹~

代码:

#include<cstdio>
#include<ctime>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
#define maxH 100
char ch[20],tem[20];
int pos[20],va[20],num,ansnum;
LL b[100],f[100],ans[100000];
LL ret;

const int N=10000010;
int pr
,p[N/10],lp;
void gp(){
for(int i=2;i<N;i++){
if(!pr[i])p[lp++]=pr[i]=i;
for(int j=0;j<lp && i*p[j]<N;j++){
pr[i*p[j]]=p[j];
if(i%p[j]==0)break;
}
}
}

void gn(LL n,int &l,LL b[],LL f[]){
int i=0,t;
l=0;
while(n>1){
if(n<N) t=pr
;
else{
t=n;
for(;i<lp && n/p[i]>=p[i];i++)
if(n%p[i]==0){
t=p[i];
break;
}
}
f[l]=0;
while(n%t==0)
n/=t,f[l]++;
b[l++]=t;
}
}

void dfs(int pos,LL now){
if(pos==num){
ans[ansnum++]=now;
return;
}
LL tem=1;
for(int i=0;i<=f[pos];i++){
dfs(pos+1,now*tem);
tem *=b[pos];
}
}
void print(LL x){
gn(x,num,b,f);
ansnum=0;
dfs(0,1);
sort(ans,ans+ansnum);
for(int i=0;i<ansnum;i++){
printf(" %I64d",ans[i]);
}
printf("\n");
}
void solve(){
ret = -1;
int len=strlen(ch);
strcpy(tem,ch);
sort(tem,tem+len);
int newlen = unique(tem,tem+len)-tem;
for(int i=0;i<len;i++){
pos[i] = lower_bound(tem,tem+newlen,ch[i])-tem;
}
for(int i=0;i<10;i++){
va[i] = i;
}
for(int i=0;i<maxH;i++){
random_shuffle(va,va+10);
while(va[pos[0]]==0){
random_shuffle(va,va+10);
}
LL now=0;
for(int j=0;j<len;j++){
now = now*10 + va[pos[j]];
}
if(ret==-1) ret=now;
else ret = __gcd(ret,now);
if(ret==1) break;
}
print(ret);
}
int main(){
int T;
gp();
srand(time(NULL));
scanf("%d",&T);
for(int i=1;i<=T;i++){
scanf("%s",ch);
printf("Case %d:",i);
solve();
}
return 0;
}


sgu 537
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: