• 清华机试 :整数拆分 题目1084


    题目描述:

    一个整数总可以拆分为2的幂的和,例如:
    7=1+2+4
    7=1+2+2+2
    7=1+1+1+4
    7=1+1+1+2+2
    7=1+1+1+1+1+2
    7=1+1+1+1+1+1+1
    总共有六种不同的拆分方式。
    再比如:4可以拆分成:4 = 4,4 = 1 + 1 + 1 + 1,4 = 2 + 2,4=1+1+2。
    用f(n)表示n的不同拆分的种数,例如f(7)=6.
    要求编写程序,读入n(不超过1000000),输出f(n)%1000000000。

    输入:

    每组输入包括一个整数:N(1<=N<=1000000)。

    输出:

    对于每组数据,输出f(n)%1000000000。

    样例输入:
    7
    样例输出:
    6

    一、母函数 解决

    起初,一看到整数拆分,先想到的就是母函数。(思维定式害死人啊,题中 n(不超过1000000) 已经提示有大数据了,3个for循环很费时)
    结果是超时!
    代码如下:
    #include <stdio.h>
    #include <string.h>
    #define MAX 1000001
    int sum[MAX];
    int temp[MAX];
    int main(){
    int n;
    while(scanf("%d",&n) != EOF){

    for(int i=0; i<=n; i++){
    sum[i] = 1;
    temp[i] = 0;
    }
    for(int i=2; i<=n; i=i<<1){
    for(int j=0; j<=n; j++){
    for(int k=0; k+j<=n; k+=i)
    temp[k+j] += sum[j];
    }
    memcpy(sum,temp,sizeof(int)*(n+1));
    memset(temp,0,sizeof(int)*(n+1));
    }
    printf("%d\n",sum[n]);
    }
    return 0;
    }


    二、找规律,用递归解决

    再网上又搜了一个递归的方法,还好没有超时。
    对于奇数n=2k+1:它的拆分的第一项一定是1,考虑去掉这个1,其实就一一对应于
    2k的拆分,因此f(2k+1)=f(2k).

    对于偶数n=2k:考虑有1和没有1的拆分。有1的拆分,与(2k-1)的拆分一一对应,与上面奇数的情况
    理由相同;没有1的拆分,将每项除以2,正好一一对应于k的所有拆分。因此f(2k)=f(2k-1)+f(k).

    需要注意f(n)会很大,不要溢出了。最终结果只要求除以十亿的余数,在int的表示范围内,
    因此不需要大数运算。注意余数的性质:(a+b)%m == (a%m+b%m)%m,所以只要对每个中间
    结果也都取余数,就不会有溢出的问题,且不改变最终输出结果。
    #include <stdio.h>
    int f[1000001];
    int main ()
    {
    int i, n;
    while(scanf("%d",&n) != EOF){
    f[0] = f[1] = 1;
    for (i=2; i<=n; ++i) {
    if (i % 2)
    f [i] = f[i-1];
    else
    f [i] = (f[i-1] + f[i/2]) % 1000000000;
    }
    printf ("%d\n", f[n]);
    }
    return 0;
    }



  • 相关阅读:
    系统架构得11个原则
    深圳变更企业法人
    Mixpanel可以做些什么?
    jira tikcet 过滤版本
    Math.random().toString(36)使用 随机生成数字与字母的组合
    javascript多个等号含义
    登陆dev,AWS需要sso,ip到白名单
    MobSDK已停止支持非严格模式版本,请按上面编译告示接入合规版本!
    thinkphp 变量修饰符
    wsl 关闭 命令
  • 原文地址:https://www.cnblogs.com/love533/p/2423119.html
Copyright © 2020-2023  润新知