现在的位置: 首页 > 综合 > 正文

【数论】整数的划分问题 【数论】整数的划分问题【转】求小于等于N的与N互质的数的和【数论】 求小于等于 N 的与N互质的所有数的乘积mod N

2017年09月30日 ⁄ 综合 ⁄ 共 5790字 ⁄ 字号 评论关闭

【数论】整数的划分问题

分类: 【数论】 285人阅读 评论(1) 收藏 举报
c

          整数的划分问题是一个很经典的问题,它的变形也非常的多,总结了一下,大概有以下几种变形:

 

1) 将 N 划分为若干个正整数的和的划分数

 

2) 将 N 划分为若干个不同的正整数的和的划分数

 

3) 将 N 划分为不超过K 个正整数的和的划分数

 

4) 将 N 划分为不超过K 个不同正整数的和的划分数

 

5) 将 N 划分为最大数不超过K 的正整数的和的划分数

 

6) 将 N 划分为若干个连续正整数的和的划分数

 

ohoh,怎么这么多@@

 

 

变形(1): 将 N 划分为若干个正整数的和的划分数。比如 6,可以这样划分:

              6
              5 + 1 
              4 + 2, 4 + 1 + 1
              3 + 3, 3 + 2 + 1, 3 + 1 + 1 + 1
              2 + 2 + 2, 2 + 2 + 1 + 1, 2 + 1 + 1 + 1 + 1
              1 + 1 + 1 + 1 + 1 + 1

             所以答案应该是 11.

             分析:

                      根据 n m的关系,考虑以下几种情况:

   (1 )当 n=1时,不论 m的值为多少( m>0),只有一种划分即 {1};

   (2)  m=1时,不论 n的值为多少,只有一种划分即 n 1 {1,1,1,...,1};

   (3)  n=m时,根据划分中是否包含 n,可以分为两种情况:

( a)划分中包含 n的情况,只有一个即 {n}

( b)划分中不包含 n的情况,这时划分中最大的数字也一定比 n小,即 n的所有 (n-1)划分。

     因此 f(n,n) =1 + f(n,n-1);

   ( 4)当 n<m时,由于划分中不可能出现负数,因此就相当于 f(n,n);

   ( 5)但 n>m时,根据划分中是否包含最大值 m,可以分为两种情况:

( a)划分中包含 m的情况,即 {m, {x1,x2,...xi}}, 其中 {x1,x2,... xi} 的和为 n-m,可能再次出现 m,因此是( n-m)的 m划分,

     因此这种划分个数为 f(n-m, m);

( b)划分中不包含 m的情况,则划分中所有值都比 m小,即 n (m-1)划分,个数为 f(n,m-1);

     因此 f(n, m) = f(n-m, m)+f(n,m-1);

             因此,设dp[n][m] 表示将 n 划分为 最大数不超过 m 的划分个数,有

                              dp[n][m] = 1                                                    ( m = 1)

                              dp[n][m] = dp[n][m-1] + 1                              ( m = n)

                              dp[n][m] = dp[n][n]                                         ( m > n)

                              dp[n][m] = dp[n][m-1] + dp[n-m][m]             ( m < n)

Code:

        

  1. #include <cstdio>  
  2. #include <cstring>  
  3. #define MAXN 500  
  4. using namespace std;  
  5. int dp[MAXN][MAXN];  
  6. int main()  
  7. {  
  8.     int i,j;  
  9.     memset(dp,0,sizeof(dp));  
  10.     for(i = 1;i < MAXN; ++i)  
  11.         dp[i][1] = 1;  
  12.     for(i = 1;i < MAXN; ++i)  
  13.         for(j = 1;j < MAXN; ++j){  
  14.             if(i > j)  
  15.                 dp[i][j] = dp[i][j-1] + dp[i-j][j];  
  16.             else if(i == j)  
  17.                 dp[i][j] = dp[i][j-1] + 1;  
  18.             else    dp[i][j] = dp[i][i];  
  19.         }  
  20. }  

 

 

变形(2):将 N 划分为若干个不同正整数的和的划分数   TOJ.3511  Staircases

             依然是DP,转移方程为 a[k][n]=a[k+1][n]+a[k+1][n-k];其中a[k][n]表示将n划分为不小于k种不同的数的划分法。

                                   初始化为 a[n][n]=1  ; a[k][n]=0 (k>n).

Code:

 

  1. #include <cstdio>  
  2. #include <cstring>  
  3. #define MAXN 500  
  4. using namespace std;  
  5. int dp[MAXN][MAXN];  
  6. int main()  
  7. {  
  8.     int i,j;  
  9.     memset(dp,0,sizeof(dp));  
  10.     for(i = 1;i < MAXN; ++i)  
  11.         dp[i][i] = 1;  
  12.     for(i = 2;i < MAXN; ++i)  
  13.         for(j = 1;j < i; ++j)  
  14.             dp[j][i] = 0;  
  15.     for(i = 2;i < MAXN; ++i)  
  16.         for(j = i-1;j >= 1; --j)  
  17.             dp[j][i] = dp[j+1][i] + dp[j+1][i-j];  
  18. }  

 

变形(3):将 N 划分为不超过K 个正整数的和的划分数

            解法:dp[i][j] 表示将 i 划分为 j 份的划分数,则转换为求 sigma( dp[N][ i ] )  (i <= K);

                        dp[i][j] 的转移方程为 dp[i-1][j-1] + dp[i-j][j];

            详细见http://wurong81.spaces.live.com/blog/cns!5EB4A630986C6ECC!254.entry

Code:

  1. #include <cstdio>  
  2. #include <cstring>  
  3. #define MAXN 500  
  4. using namespace std;  
  5. int dp[MAXN][MAXN];  
  6. int main()  
  7. {  
  8.     int i,j;  
  9.     // 求将某个数划分为 m 份的划分数  
  10.     for(i = 1;i < MAXN; ++i)  
  11.         for(j = 1;j <= (i<m?i:m); ++j)  
  12.             dp[i][j] = dp[i-1][j-1] + dp[i-j][j];  
  13. }  

 

变形(4):将 N 划分为不超过K 个不同正整数的和的划分数

          解法:即为变形2的方程意义。a[k][n] 表示将 N 划分为不超过K份不同的数的和的划分数

 

变形(5):

变形(6): 这个最简单了。N 可以写为连续K(K >= 2)个正整数的和,则K <= sqrt(2*N);

               令 i 从 K 到 2 循环,如果 i 为奇数 且 N %i == 0,则可分解为 i 个数,第一个数为 N/i - i/2;

                                                   如果 i 为偶数 且 N %i == i/2,则可分解为i 个数,第一个数为 (N-1)/i - i/2 + 1;

【转】求小于等于N的与N互质的数的和

分类: 【数论】 200人阅读 评论(0) 收藏 举报
问题描述:
给出一个N,求1..N中与N互质的数的和

if gcd(n,i)=1 then gcd(n,n-i)=1 (1<=i<=n)

反证法:
         如果存在K!=1使gcd(n,n-i)=k,那么(n-i)%k==0
         而n%k=0
         那么必须保证i%k=0
         k是n的因子,如果i%k=0那么 gcd(n,i)=k,矛盾出现;
         于是问题变的非常简单: ANS=N*phi(N)/2
         i,n-i总是成对出现,并且和是n
        于是可能就有人问了,如果存在n-i=i那不是重复计算?
         答案是不会
         因为:
                 n=2*i->i=n/2
         1.如果n是奇数,那么n!=2*i,自然也不存在 n-i=i和重复计算之说
         2.如果n是偶数,n=2*i成立,gcd(n,n/2)必然为n的一个因子,这个因子为1当且仅当n==2
         于是对于n>2的偶数,绝对不存在gcd(n,n/2)=1所以更别说什么重复计算了
         对于n==2
         ans=2*1/2=1,正好也满足
         所以得到最终公式:
        ans=N*phi(N)/2 

【数论】 求小于等于 N 的与N互质的所有数的乘积mod N

分类: 【数论】 209人阅读 评论(0) 收藏 举报

           求小于等于N 的所有与N互质的数的乘积modN。这是今天训练赛的一道题。RP极高的我们愣是找出了结论。

           结论:对于 1,2,4,P^n, 2*P^n,答案为 N-1,其余情况都是1。也就是说,1,2,4,以及只有一个质因子(奇数)或者它的1/2只有一个

                       质因子(偶数),答案是N-1.其余情况答案均是 1。

           附程序:

  1. #include <cstdio>  
  2. #include <cstring>  
  3. #include <algorithm>  
  4. #include <vector>  
  5. #include <queue>  
  6. #define min(a,b)  ((a)<(b)?(a):(b))  
  7. #define INF 0x1f1f1f1f  
  8. #define MAXN 40000  
  9. using namespace std;  
  10. int p[MAXN],cont[50];  
  11. bool flag[MAXN];  
  12. int k,num;  
  13. void get_prime(){  
  14.     memset(flag,false,sizeof(flag));  
  15.     k = 0;  
  16.     for(int i = 2;i < MAXN; ++i){  
  17.         if(!flag[i])  
  18.             p[k++] = i;  
  19.         for(int j = 0;j < k && i*p[j] < MAXN; ++j){  
  20.             flag[i*p[j]] = true;  
  21.             if(i % p[j] == 0) break;  
  22.         }  
  23.     }  
  24. }  
  25. bool cal(int n){  
  26.     num = 0;  
  27.     for(int i = 0;p[i] <= n && i < k; ++i){  
  28.         if(n%p[i] == 0){  
  29.             while(n%p[i] == 0)  
  30.                 n /= p[i];  
  31.             num++;  
  32.             if(num > 1) return false;  
  33.         }  
  34.         if(n == 1) break;  
  35.     }  
  36.     if(n > 1) num++;  
  37.     if(num > 1) return false;  
  38.     return true;  
  39. }  
  40.       
  41.       
  42. int main()  
  43. {  
  44.     int n;  
  45.     get_prime();  
  46.     while(scanf("%d",&n) != EOF){  
  47.         if(n != 4 && n % 4 == 0){  
  48.             printf("1/n");  
  49.             continue;  
  50.         }  
  51.         if(n%2 == 0){  
  52.             if(cal(n/2)){  
  53.                 printf("%d/n",n-1);  
  54.                 continue;  
  55.             }else{  
  56.                 printf("1/n");  
  57.                 continue;  
  58.             }  
  59.         }else{  
  60.             if(cal(n)){  
  61.                 printf("%d/n",n-1);  
  62.                 continue;  
  63.             }else{  
  64.                 printf("1/n");  
  65.                 continue;  
  66.             }  
  67.         }  
  68.     }  
  69. }  

抱歉!评论已关闭.