- 注册时间
 - 2007-12-27
 
- 最后登录
 - 1970-1-1
 
- 威望
 -  星
 
- 金币
 -  枚
 
- 贡献
 -  分
 
- 经验
 -  点
 
- 鲜花
 -  朵
 
- 魅力
 -  点
 
- 上传
 -  次
 
- 下载
 -  次
 
- 积分
 - 49017
 
- 在线时间
 -  小时
 
 
 
 
 
 
 | 
 
 
发表于 2019-11-1 08:48:40
|
显示全部楼层
 
 
 
试着测试一下随机mathe 
代码假设Fans给出的目标数据就是按0,1,2,...,N-1顺序给出(但是mathe不知道) 
- #include <stdio.h>
 
 - #include <time.h>
 
 - #include <string.h>
 
 - #include <stdlib.h>
 
 - #include <math.h>
 
 - #include <vector>
 
  
- #ifndef N
 
 - #define N 20
 
 - #endif
 
  
- #define TC 8
 
  
- #define TARGET 1
 
  
- struct Data{
 
 -     char v[N];
 
 -     int c;
 
 - };
 
  
- std::vector<Data> usedlist;
 
 - std::vector<Data> leftlist;
 
 - char leftc;
 
 - char avail[N][N];
 
 - double tvalue;
 
 - double ve;
 
 - void init()
 
 - {
 
 -     tvalue = log(2*M_PI*N)/2+N*(log(N)-1)-log(TARGET);
 
 -     ve=exp(-1.0);
 
 -     int i,j;
 
 -     leftc=N;
 
 -     for(i=0;i<N;i++){
 
 -        for(j=0;j<N;j++)avail[i][j]=j;
 
 -     }
 
 - }
 
  
- void dumpleft()
 
 - {
 
 -     int i;
 
 -     int j;
 
 -     for(i=0;i<leftlist.size();i++){
 
 -        printf("\n");
 
 -        for(j=0;j<N;j++)printf("%d ",leftlist[i].v[j]);
 
 -     }
 
 -     printf("\n");
 
 - }
 
  
- char used[N];
 
 - char mc[N*N];
 
 - char umc[N*N];
 
 - Data tryv;
 
 - int depth;
 
 - void search()
 
 - {
 
 -     if(depth>=N){
 
 -         leftlist.push_back(tryv);
 
 -         return;
 
 -     }
 
 -     int i,j;
 
 -     for(i=0;i<usedlist.size();i++){
 
 -         if(mc[i]>usedlist[i].c||umc[i]>N-usedlist[i].c)return;
 
 -     }
 
 -     for(i=0;i<leftc;i++){
 
 -         int k = avail[depth][i];
 
 -         if(used[k]==0){//The value has not been used, try use it
 
 -             used[k]=1; tryv.v[depth]=k;if(k==depth)tryv.c++;
 
 -             for(j=0;j<usedlist.size();j++){
 
 -                 if(usedlist[j].v[depth]==k){
 
 -                     mc[j]++;
 
 -                 }else{
 
 -                     umc[j]++;
 
 -                 }
 
 -             }
 
 -             depth++;
 
 -             search();
 
 -             depth--;
 
 -             for(j=0;j<usedlist.size();j++){
 
 -                 if(usedlist[j].v[depth]==k){
 
 -                     mc[j]--;
 
 -                 }else{
 
 -                     umc[j]--;
 
 -                 }
 
 -             }
 
 -             used[k]=0;if(k==depth)tryv.c--;
 
 -         }
 
 -     }
 
 - }
 
  
- void collect_lefts()
 
 - {
 
 -     depth=0;
 
 -     tryv.c=0;
 
 -     memset(used,0,sizeof(used));
 
 -     memset(mc,0,sizeof(mc));
 
 -     memset(umc,0,sizeof(umc));
 
 -     search();
 
 - }
 
  
- int trygenrand(Data& d)
 
 - {
 
 -     char cused[N];
 
 -     memset(cused,0,sizeof(cused));
 
 -     int i,j,k;
 
 -     d.c=0;
 
 -     for(i=0;i<N;i++){
 
 -         j=rand()%leftc;
 
 -         int choice=-1;
 
 -         for(k=j;k<leftc;k++){
 
 -            if(cused[avail[i][k]]==0){choice=k;break;}
 
 -         }
 
 -         if(choice<0){
 
 -            for(k=0;k<j;k++){
 
 -               if(cused[avail[i][k]]==0){choice=k;break;}
 
 -            }
 
 -         }
 
 -         if(choice<0)return -1;
 
 -         cused[avail[i][choice]]=1;
 
 -         d.v[i]=avail[i][choice];
 
 -         if(d.v[i]==i)d.c++;
 
 -     }
 
 -     return 0;
 
 - }
 
  
- void genrand(Data& d)
 
 - {
 
 -     while(trygenrand(d)<0);
 
 -     int i,j;
 
 -     usedlist.push_back(d);
 
 -     if(d.c==0){
 
 -        for(i=0;i<N;i++){
 
 -            for(j=0;j<leftc;j++){
 
 -                if(d.v[i]==avail[i][j])break;
 
 -            }
 
 -            if(j>=leftc){
 
 -                fprintf(stderr,"Internal error\n");
 
 -                exit(-1);
 
 -            }
 
 -            for(;j<leftc-1;j++){
 
 -                avail[i][j]=avail[i][j+1];
 
 -            }
 
 -        }
 
 -        leftc--;
 
 -     }
 
 -     double dd=ve;for(i=0;i<d.c;i++)dd/=(i+1);
 
 -     tvalue+=log(dd);
 
 - }
 
  
 
- int main()
 
 - {
 
 -     Data d;
 
 -     srand(time(NULL));
 
 -     init();
 
 -     int t=0;
 
 -     while(leftc>TC){
 
 -         genrand(d);
 
 -         t++;
 
 -     }
 
 -     printf("try %d times to reach small probability, leftc = %d\n", t, leftc);
 
 -     collect_lefts();
 
 -     printf("Total %d left\n", (int)leftlist.size());
 
 -     dumpleft();
 
 - }
 
 
  复制代码 
测试了含20个数字,而mathe总是瞎猜直到听到12次Fans说你全错了位置在统计余下的可能 
每次统计可能会很快(不到一秒)也可能会花费数分钟 
试验结果 
第一次: 
try 72 times to reach small probability, leftc = 8 
Total 1 left 
 
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 
第二次: 
try 57 times to reach small probability, leftc = 8 
Total 1 left 
 
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 
 
第三次: 
try 53 times to reach small probability, leftc = 8 
Total 1 left 
 
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 
 
第四次: 
try 48 times to reach small probability, leftc = 8 
Total 5 left 
 
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 
5 1 12 0 4 19 6 8 17 9 10 3 15 13 14 2 16 7 18 11 
5 1 17 0 4 19 6 8 3 9 10 12 15 13 14 2 16 7 18 11 
5 1 17 0 14 4 6 8 3 9 11 12 15 13 10 2 16 7 18 19 
9 17 12 8 14 0 6 15 4 5 11 3 19 1 10 2 16 7 18 13 
于是我们需要补猜一次 
5 1 17 * 4 *  ************* 
就可以完全区分了。 
 
第五次: 
try 43 times to reach small probability, leftc = 8 
Total 2 left 
 
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 
0 1 2 3 4 5 6 7 8 13 10 11 12 9 14 15 16 17 18 19 
 
第六次: 
try 42 times to reach small probability, leftc = 8 
Total 2 left 
 
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 
0 1 2 3 4 5 6 7 8 9 19 11 12 13 14 15 16 17 18 10 
 
第七次: 
try 56 times to reach small probability, leftc = 8 
Total 1 left 
 
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 
 
第八次: 
try 70 times to reach small probability, leftc = 8 
Total 1 left 
 
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 
 
第九次: 
try 61 times to reach small probability, leftc = 8 
Total 1 left 
 
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 
 
第十次 
try 51 times to reach small probability, leftc = 8 
Total 1 left 
 
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 
 
波动还是挺大的。 
另外看来随机测试的次数还可以减少,提前分析规律会有好处。只是需要计算力非常强大,mathe远远不够。 |   
 
 
 
 |