posts - 99,  comments - 8,  trackbacks - 0
 
#include <stdio.h>
#
include <stdlib.h>
int main ()
{
    int  i;
    char R;
    int r;
    
while ( (R = getchar()) != EOF )
    {
            getchar();
          
//将 R 转化为数字 
          
if ( '0' <= R && R <= '9')
             r 
= R - '0';
             
else if ( 'A' <= R && R <= 'Z' ) 
                  r 
= R - 'A' + 10;
                  
else if ( 'a' <= R && R <= 'z' )
                  r 
= R - 'a' + 36;
             
for (i = 2; i <= 62; i++)
             {
                 
if ( (i - 1% r == 0 )
                 {
                      printf (
"%d\n", i);
                      
break;
                 }
                 
else
                     
continue;
             }
    }
    
//system("pause");
    
return 0;
}
posted @ 2010-08-29 11:41 雪黛依梦 阅读(314) | 评论 (0)编辑 收藏
#include <stdio.h>
#
include <stdlib.h>
#
include <string.h>
#
define LENGTH 6  //小数的位数(含小数点) 

//将字符转化为数字 
unsigned int change (char s[LENGTH], unsigned int s1[LENGTH 
- 1])
{
     int ss[LENGTH 
- 1];  //ss 放未逆置的整数 
     memset (ss, 0, sizeof(ss));
     
     int k 
= 0 ;
     
for (int i = 0; i < LENGTH && s[i]; ++i)  //考虑特殊数据如:0.0001 
     {
         
if (s[i] != '.')
            ss[k
++= s[i] - '0';
     } 
     
for (int j = 0;j < LENGTH - 1; j++)
     {
         s1[j] 
= ss[LENGTH - 2 - j];  
     }
     
     int m 
= 0;
     
while ( (s[m] != '.'&& s[m] )
           
++m; 
           
return LENGTH - 1 - m;   //小数点位数 


//大数乘法运算 
//函数返回 s2 
void mu1 (unsigned int s1[LENGTH 
- 1],unsigned int s2[130])
{
     int ss[
130];
     memset ( ss, 0, sizeof(ss) );
     
     
for ( int i = 0; i < LENGTH - 1; i++)
         
for (int j = 0;j < 130; j++)  //难点:因为返回新的s2之后位数会增加 最多时 5* 25 = 125 
         ss [i 
+ j] += s1[i] * s2[j];
     
     
//将 两个大数相乘得的积ss中进行进位处理后放到s2 中  
     int c 
= 0;
     
for (int i = 0;i < 130;i++)
     {
         s2[i] 
= (c + ss[i]) % 10;
         c 
= (c + ss[i]) / 10;
     } 
}

int main()
{
    int n;
    char s[LENGTH];  
//要处理的幂 R 
    unsigned int s1[LENGTH 
- 1];  //将 R 转化成数字 
    unsigned int s2[
130];
     
    
while(scanf ("%s%d", s, &n) != EOF)
    {
        memset (s1, 0, sizeof (s1));
        memset (s2, 0, sizeof (s2)); 
        
        int j 
= change (s, s1);      //得到小数点所在位置 
        change (s,s2);              
//得到s2 和 s1 进行幂运算 
        
for ( int i = 1; i < n; i ++)
            mu1 (s1,s2); 
        
        
//在s2中前面的代表小数位,后面的代表整数位,
        
//所以关键是通过数值关系找到小数点的位置
      
      
         
//例:0.1010  * 0.1010 = 0.01020100  
        int m 
= 129;//去掉前导0 
        
while ( (!s2[m]) && m)
        
--m;
        
        int k 
= 0; //去掉尾0                       
        
while ( ( !s2[k] ) && (k < 130))                                                           
        
++k;
        
        
//输出整数位 
        
for (int i = m; i >= n * j; i--)
            printf (
"%d",s2[i]);
            
        
//输出小数点
        
if ( j && n * j >= k + 1
        printf (
".");
        
        
for (int i = n*-1; i >= k; --i)
        printf (
"%d", s2[i]);
        printf (
"\n");
    }
    
    
return 0;
   
// system ("pause");   
}
posted @ 2010-08-29 11:35 雪黛依梦 阅读(1875) | 评论 (0)编辑 收藏
#include <stdio.h>
#
include <stdlib.h>

#define Tp 23
#
define Te 28
#
define Ti 33

int main ()
{
    int p, e, i, d;
    
    int num 
= 1;
    
    
while (scanf ("%d%d%d%d"&p, &e, &i, &d) != EOF && (p != -1 && e != -1 && i != -1 && d != -1))
    {
          int j;
          
for ( j = 1; j <= 21252; j ++)
          {
              
if ( ((j - p) % Tp == 0) && ((j - e) % Te == 0) && ((j - i) % Ti ==0) )
              {
                   
if ( j - d > 0)
                   printf (
"Case %d: the next triple peak occurs in %d days.\n", num, j - d);
                   
else  
                        printf (
"Case %d: the next triple peak occurs in %d days.\n", num, j - d + 21252);
                   
                   
break;
              }
          }
          num 
++;
    } 
    system (
"pause");
    
return 0;
}
http://tiandiwuyong1989.blog.163.com/blog/static/122572981200962121733/

本题就是要求得满足下面条件的 x  的值:
( x - p ) % Tp = 0;    ( x - e ) % Te = 0;    ( x - i ) % Ti = 0;   
由同余可得:x % Tp  =  p % Tp    = a
                        x % Te  =  p % Te    = b
                        x % Ti   =  p % Ti     = c
再由中国剩余定理就可以知道了!
//2.用中国剩余定理解
#include <stdio.h>
#
include <stdlib.h>
int main ()
{
    int p, e, i , d, x;
    int Tp 
= 23, Te = 28, Ti = 33;
    int num 
= 1;
    
while (scanf ("%d%d%d%d"&p, &e, &i, &d ) != EOF && (p != -1 && e != -1 && i != -1 && d != -1) )
    {
          int a 
= p % Tp;
          int b 
= e % Te;
          int c 
= i % Ti;
          
          int n1, n2, n3;
          
          
for (int j = 1; j < 33; j ++)
          {
              
if ( (23 * 28 * j) % 33 == 1)
              {
                  n1 
= j;
                 
break;
              }
                 
          }
          
for (int j = 1; j < 28; j ++)
          {
              
if ( (23 * 33 * j) % 28 == 1)
              {
                  n2 
= j;
                 
break;
              }
                 
          }
          
for (int j = 1; j < 23; j ++)
          {
              
if ( (33 * 28 * j) % 23 == 1)
              {
                  n3 
= j;
                 
break;
              }
                 
          }

         
          
          x 
= (28 * 23 * n1 * c + 23 * 33 * n2 * b + 28 * 33 * n3 * a ) % (23 * 33 * 28);
          
         
if ( x - d > 0)
                   printf (
"Case %d: the next triple peak occurs in %d days.\n", num, x - d);
                   
else  
                        printf (
"Case %d: the next triple peak occurs in %d days.\n", num, x - d + 21252);
          
          num
++;
    }
    
//system ("pause");
    
return 0;

posted @ 2010-08-29 11:10 雪黛依梦 阅读(413) | 评论 (0)编辑 收藏
 
1、先计算Gcd(a,b),若n不能被Gcd(a,b)整除,则方程无整数解;否则,在方程两边同时除以Gcd(a,b),得到新的不定方程a' * x + b' * y = n',此时Gcd(a',b')=1;
2、利用上面所说的欧几里德算法求出方程a' * x + b' * y = 1的一组整数解x0,y0,则n' * x0,n' * y0是方程a' * x + b' * y = n'的一组整数解;
3、根据数论中的相关定理,可得方程a' * x + b' * y = n'所有整数解为:
x = n' * x0 + b' * t
y = n' * y0 - a' * t   (t为整数)
上面的解也就是a * x + b * y = n 的全部整数解。  
 
此时方程的所有解为:x=c*k1-b*t
x的最小的可能值是0
§x=0,可求出当x最小时的t的取值,但由于x=0是可能的最小取值,实际上可能x根本取不到0,那么由计算机的取整除法可知:由 t=c*k1/b算出的t,代回x=c*k1-b*t中。 §求出的x可能会小于0,此时令t=t+1,求出的x必大于0;如果代回后x仍是大于等于0的,那么不需要再做修正。
//满足关系:(x + m * s) - (y + n *s) = k*l  (k= 0 1 2 )即:(n - m)*s + l*k = x-y; 
//利用拓展的欧几里得解出可能的s 
#include <stdio.h>
#include <stdlib.h>

//求最大公约数 
__int64 gcd (__int64 a, __int64 b) 
{
    if (b == 0)
       return a;
       else
       gcd (b, a % b);
}

//求得满足 a*x + b*y = d;的x  y 
__int64 ex_Gcd (__int64 a, __int64 b, __int64 &x1, __int64 &y1)
{
    if ( b == 0 )
    {
         x1 = 1;
         y1= 0;
         return a;
    }
    
    int r = ex_Gcd( b, a%b, x1, y1);
    
    int temp = x1;
    x1 = y1;
    y1 = temp - a/b * y1;
}

int main ()
{
    __int64  x, y, m, n, l;
    int a, b, product, d;//a b 的最大公约数 product 
    int s, k;
    __int64 s1, k1, s2, k2;
    
    while ( scanf ("%I64d%I64d%I64d%I64d%I64d", &x, &y, &m, &n, &l ) != EOF )
    {
          a = n - m;
          b = l;
          d = x-y;
          product = gcd (a,b);
          
          if ( d % product != 0 )
             printf ("Impossible\n");
             else
             {
                 a = a / product;
                 b = b / product;
                 d = d / product;
                 ex_Gcd (a, b, s1, k1);               //得到(n-m)/product * s + l/product * k = 1;的 s k的解
                 s2 = d * s1;                     //得到(n-m)/product * s + l/product * k = d;的 s k的解
                 k2 = d * k1; 
                 
                 int t;
                 //s = s2 - b * t;    用下面的方法处理满足条件的解 
                 //k = k2 - a * t;
                 
                 t = s2 / b;
                 s = s2 - b * t;
                 if ( s <= 0)
                 {
                      s += b;
                 } 
                 printf ("%d\n", s);
             }
    }
    //system ("pause");
    return 0 ;
}
posted @ 2010-08-28 22:46 雪黛依梦 阅读(634) | 评论 (0)编辑 收藏

讲解拓展的欧几里德算法:
一、内容: 
对于不完全为 0 的非负整数 abgcdab)表示 ab 的最大公约数,必然存在整数对 xy ,使得 gcdab=ax+by。如果gcd(a, b)d,那么一定存在xy满足axby=d;

二、推导: 如何求  x   y 
a>b 
1,显然当 b=0gcdab=a。此时 x=1y=0
2ab<>0
ax1+by1=gcd(a,b);
bx2+(a mod b)y2=gcd(b,a mod b);
根据朴素的欧几里德原理有 gcd(a,b)=gcd(b,a mod b);
:ax1+by1=bx2+(a mod b)y2;
:ax1+by1=bx2+(a-(a/b)*b)y2=ay2+bx2-(a/b)*by2;
根据恒等定理得:x1=y2; y1=x2-(a/b)*y2;
这样我们就得到了求解 x1,y1 的方法:x1y1 的值基于 x2y2.
三、算法如下:
 
int exGcd(int a, int b, int &x, int &y)
{
if(b == 0)
{
x = 1;
y = 0;
return a;
}
int r = exGcd(b, a % b, x, y);   
int temp = x;      //   x 即 返回的x2
x = y;                   // x  即要求的 x1
y = temp - a / b * y;   
}                               理解递归 例:a = 48,b = 22 得到   x = 11, y = -24
posted @ 2010-08-28 22:05 雪黛依梦 阅读(289) | 评论 (0)编辑 收藏
#include <stdio.h>
#include <stdlib.h>

int gcd (int big, int small)
{
    if (small==0)
       return big;
       else
       {
           gcd (small, big%small);
       }
}
int main ()
{
    int big, small, temp;
    
    while ( scanf ("%d%d", &big, &small) != EOF )
    {
          if (big < small)
          {
                  temp = big;
                  big = small;
                  small = temp;
          }
          int b = big;
          int s = small;
          int result = gcd (big, small);
          printf ("%d\n", (b*s) / result);
    } 
    system("pause");
    
    return 0;
}
posted @ 2010-08-28 21:58 雪黛依梦 阅读(356) | 评论 (0)编辑 收藏
/*1.朴素法 只适合 N 很小的时候    复杂度:n * sprt(n) 
#include <stdio.h>
#include <stdlib.h>
int main ()
{
    int N;
    scanf ("%d", &N);
    
    int j,i ;
    for ( i = 2; i <= N; i ++)  //i
    {
        for ( j = 2;  j*j <= i; j++ )// j <= 根号i
        {
            if ( i % j == 0 )
               break;
        }
        if ( j*j > i )
           printf ("%d ",i); 
    }
    system("pause");
    return 0;
}
*/

/*2.最简单的素数衰选法:思路:因为偶数不可能是素数,而且第一个奇数是素数,
//故定义一个prime数组,将其下标为偶的初始化为flase,而下表为奇的初始化true,并且奇数的偶数倍false 
//输出 0-100内的素数 
//缺点: 奇数的倍数赋为false 时,出现了同一个多次标记;如:3 5 的倍数 15  被两次标记 
#include <stdio.h>
#include <stdlib.h>
int main ()
{
    bool prime[101];
    
    int i, j, k;
    for ( i = 0; i < 101; i++)
    {
        if ( i % 2== 0)
           prime[i] = false;
           else
               prime[i] = true;
    } 
    prime[2] = true;prime[1] = false;//特例处理 
    
    for ( j = 3; j < 101; j++)//将奇数的倍数赋为false 
    {
        if ( prime[j] == true )
        {
             for (int m = 2*j; m < 101; m+=j)
             {
                 prime[m] = false; 
             }
        }
    }
    
    for ( k = 0; k < 101; k ++)
    {
        if (prime[k]==true)
           printf ("%d ", k);
    }
    
    system("pause");
    return 0;
    
}
*/


/*3.Eraosthenes筛法:得到一个新的素数后将它的倍数剔除掉
//缺点:剔除素数的倍数时,出现了同一个多次标记:如 2  3  的倍数   6    12 
#include <stdio.h>
#include <stdlib.h>
int main ()
{
    static int prime[101];
    prime[0] = 1;  prime[1] = 1;
    
    int i , j;
    for ( i = 2; i < 101; i ++)
    {
        if ( ! prime[i] )  //是素数 
        {
             for (j = 2*i; j < 101; j+=i)
             {
                 prime[j] = 1;
             } 
        }
    }
    
    for (int m = 2; m < 101; m++)
    {
        if ( !prime[m] )
        printf ("%d ",m);
    }
    system("pause");
    return 0;
}
*/

//线性Eraosthenes筛选素数的方法:同样的思路避免了上述的缺点
//理解这种机制 
#include <stdio.h>
#include 
<stdlib.h>
#define MAXSIZE 1000
int tag[MAXSIZE + 1];
int main ()
{
    
    
int prime[MAXSIZE];
    
    
int i, j;
    
    
int cn = 0;
    
for (i = 2; i< MAXSIZE + 1; i ++)
    
{
        
if ( !tag[i] )
            prime[cn
++= i;

        
for ( j = 0; (j < cn) && (prime[j] * i < MAXSIZE + 1) ; j++ )
        
{
            tag[ i 
* prime[j] ] = 1;    //最多标记到本身的倍数,而prime【j】的最大恰好为 i ,而 最大时 j = cn; 

            
if ( i % prime[j] == 0 )
                
break;
        }

        
    }

    
    printf (
"%d\n", cn);
    
    
    
for (int m = 0; m < cn; m ++)
    
{
        printf (
"%d ",prime[m]);
    }

    printf (
"\n");
    
    
    system(
"pause");
    
return 0;
}
 
 

 

posted @ 2010-08-28 21:32 雪黛依梦 阅读(402) | 评论 (0)编辑 收藏

 

//把任意长度的输入,通过散列算法,变换成固定长度的输出 
// 经典的哈希算法  这个题目在减少复杂度的方面真的有很多的技巧值得我学习 
// 因为直接存储四项的值 有四重循环,这样耗时很多,所以开一个满足题意要求的数组存储
//等式两边的计算值如果出现下标相等就说明满足题意,同时起到了计数的作用
//因为平方的作用从 1 -- 100 循环减少了复杂度 ,只是记得最后一定要乘以一个16哦! 
#include <iostream>
#include 
<string>
using namespace std;

int hash[2000010]; 
int main ()
{
    
int a, b, c, d;
    
while ( scanf ("%d %d %d %d"&a, &b, &c, &d ) != EOF )
    
{
          
if ( ( a > 0 && b > 0 && c > 0 && d > 0 ) || ( a < 0 && b < 0 && c < 0 && d < 0 ))
          
{
               printf (
"0\n");
               
continue;
          }

          memset ( hash, 
0sizeof (hash) );
          
int count = 0;
          
for ( int i = 1; i <= 100; i ++ )
          
{
              
for ( int j = 1; j <= 100; j ++ )
              
{
                  hash[ a * i * i + b * j * j + 1000000 ] ++;       //每一个不同的a*x1^2 + b*x2^2 hash值都是 1   
              }
          }
 
          
          
for ( int i = 1; i <= 100; i ++ )
          
{
              
for ( int j = 1; j <= 100; j ++ )
              

                  count += hash[ 1000000 - c * i * i - d * j * j ]; //如果出现了相同的hash值 则:+ 1            
              }
          }
 
          printf (
"%d\n"16 * count);                                                        //反之count会 = 0 
    }


    
//system ("pause");          
     return 0;
}

posted @ 2010-08-28 21:16 雪黛依梦 阅读(444) | 评论 (0)编辑 收藏
用 hash  做
Accepted 1280 0MS 292K 1236B G++

//典型的hash: 用数组下标表示两两相加所得到的和,开辟一个满足题意的大小的数组 sum,
//这样下标由大到小输出m个就可以 
 
#include 
<iostream>
#include 
<string>
using namespace std;

int main ()
{
    
int a[3001];
    
int sum[10001]; 
    
int n, m;
    
while ( scanf ("%d %d"&n, &m) != EOF )
    
{
          memset ( a, 
0sizeof (a) );
          memset ( sum, 
0sizeof (sum) );
          
for ( int i = 0; i < n; i ++ )
          
{
              scanf (
"%d"&a[i]);
          }

          
          
int temp;
          
for ( int i = 0; i < n; i ++ )
          
{
              
for ( int j = i + 1; j < n; j++ )
              
{
                  temp 
= a[i] + a[j];
                  sum[temp] 
++;
              }

          }

          
          
int count = 0;      //输出前 m  个数
          for ( int i = 10001; i >= 0 ; i -- )
          
{
              
if ( sum[i] )
              
{
                   
for (int j = 0; j < sum[i]; j ++)
                   
{
                       count 
++;
                       count 
== 1 ? printf ("%d", i) : printf (" %d", i);
                          if ( count == m )
                            
break;
                   }

              
  }
 
                      if ( count == m )
                      
break;

          }

          
          printf (
"\n");
    }


    
// system ("pause");
     return 0;
}


所以改用sort排序后再输出
Accepted 1280 843MS 17888K 1304B G++
//典型的hash: 用数组下标表示两两相加所得到的和,开辟一个满足题意的大小的数组 sum,
//这样下标由大到小输出m个就可以 
 
#include <iostream>
#include <string>
using namespace std;

int sum[4500000];          //开全局数组才能过
bool cmp ( const int &a, const int &b )
{
     return a > b;
}

int main ()
{
    int a[3001];
    
    int n, m;
    while ( scanf ("%d %d", &n, &m) != EOF )
    {
          memset ( a, 0, sizeof (a) );
          memset ( sum, 0, sizeof (sum) );
          //输入处理 
          for ( int i = 0; i < n; i ++ )
          {
              scanf ("%d", &a[i]);
          }
          
          //两数求和 
          //int k = n * ( n - 1 ) / 2;
          int temp = 0;
          for ( int i = 0; i < n; i ++ )
          {
              for ( int j = i + 1; j < n; j ++ )
              {
                  sum[temp ++] = a[i] + a[j];
              }
          }
          
          sort ( sum, sum + temp, cmp );
          
          int count = 0;
          for ( int i = 0; i< temp; i ++ )
          {
              count ++;
              count == 1 ? printf ("%d", sum[i]): printf (" %d",sum[i]);
              
              if ( count == m )
              break;
          }
          printf ("\n");
    }

    // system ("pause");
     return 0;
}
posted @ 2010-08-28 16:43 雪黛依梦 阅读(418) | 评论 (0)编辑 收藏

//这个题目如果理解了除法的机制就简单,对于这种 1 / n 的除法因为每次都是用模的10倍去除以除数,
//所以如果出现了模相同必将意味着出现循环节,所以这里用一个标记数组来跳出循环
//这里很容易忽略负数,同时特殊的数  1 的处理

//忘了把最开始的temp = 1 标记为 true  所以WA 了  

#include <iostream>
#include 
<string>
using namespace std;

int main ()
{
    
int t, n;
    
int mark[100001];
    
int res[100001]; 
    
while ( scanf ("%d"&t )  != EOF )
    
{
          
for ( int i = 0; i < t; i ++ )
          
{
              scanf ( 
"%d"&n );
              
if ( n < 0 )
              
{
                   printf (
"-");
                   n 
= -n;
              }

              
              
if ( n == 1 )
              
{
                    printf (
"1\n ");
                    
continue;
              }

                           
              memset ( mark, 
falsesizeof (mark) );
              memset ( res, 
falsesizeof (mark) );
              
int temp = 1;       //最先的模是 1 
              mark [ temp ] = true
              
int cnt = 0;
              
while ( temp )
              
{
                    temp 
*= 10;
                    res[cnt 
++= temp / n;
                    temp 
%= n;
                    
if ( mark[temp] )
                       
break;
                    mark[temp] 
= true;
              }
 
              printf (
"0.");
              
for ( int i = 0; i < cnt; i ++ )
              
{
                  printf (
"%d", res[i]);
              }

              printf (
"\n");
          }

    }
    

    
// system ("pause");
     return 0;
}

posted @ 2010-08-28 15:10 雪黛依梦 阅读(450) | 评论 (0)编辑 收藏
仅列出标题
共10页: 1 2 3 4 5 6 7 8 9 Last 
<2024年5月>
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

常用链接

留言簿(4)

随笔分类

随笔档案

文章档案

搜索

  •  

最新评论

阅读排行榜

评论排行榜