洛谷---数学---数论

洛谷---数学---数论

http://www.luogu.org

单看 数学 数论 的书,纯理论,看不进,决定还是从做题开始,不明白的地方再看书,以上机训练,促进看书,同样 从 简单--->难,进行相应训练。

//P1554 梦中的统计
//N-M ≤500,000数据范围,估量了一下,不会超时
//开辟数组c[i],c[i]统计 i这个数的个数
//样例通过,提交AC 2018-1-27 7:48

//该题 数学 考点,将整数的每一位数取出。

#include <stdio.h>
#include <string.h>
int c[15];
void count(int n){
    while(n){
        c[n%10]++;
        n/=10;
    }
}
int main(){
    int m,n,i;
    memset(c,0,sizeof(c));
    scanf("%d%d",&m,&n);
    for(i=m;i<=n;i++)count(i);
    for(i=0;i<=9;i++)printf("%d ",c[i]);
    return 0;
}

//P1615 西游记公司
//该题的难度,在于数据读取,转化为整数,要注意时间是60进制
//样例通过,提交AC 2018-1-27 19:25
//该题收获,发现scanf格式读取方式,同时发现scanf可以略过前导0进行读取
#include <stdio.h>
int main(){
    int h1,m1,s1,h2,m2,s2;
    long long ans;
    scanf("%d:%d:%d",&h1,&m1,&s1);
    scanf("%d:%d:%d",&h2,&m2,&s2);
    scanf("%lld",&ans);
    printf("%lld",ans*(h2*3600+m2*60+s2-h1*3600-m1*60-s1));
    return 0;
}
//P1720 月落乌啼算钱
//该题利用系统的数学函数进行计算
//样例通过,提交AC 2018-1-27 19:49
#include <stdio.h>
#include <math.h>
int main(){
    int n;
    double a,b,ans;
    scanf("%d",&n);
    a=(1+sqrt(5))/2,b=(1-sqrt(5))/2;
    ans=(pow(a,n)-pow(b,n))/sqrt(5);
    printf("%.2lf",ans);
    return 0;
}

//P1887 乘积最大3
//乘积最大,这些数字要尽可能的接近
//涉及 除 余 运算
//样例通过,提交AC 2018-1-27 21:13
//该题需要具备高中数学,均值不等式的知识
#include <stdio.h>
int main(){
    int n,m,a,b,i;
    scanf("%d%d",&n,&m);
    a=n/m,b=n%m;
    for(i=1;i<=m-b;i++)
        printf("%d ",a);
    for(i=1;i<=b;i++)
        printf("%d ",a+1);    
    return 0;
}
//P2705 小球
//弄懂样例是关键所在
//样例1 3蓝球 放 3蓝盒 2红球 放 2红盒 答案 3*400+2*100=1400
//样例2 2红球 放 2蓝盒 2蓝球 放 2红盒 1蓝球 放 1蓝盒 答案 4*300+400=1600
//一开始 想动用 背包,问题复杂化了,
//仔细一想,红放红,蓝放蓝;红蓝互放,剩下什么颜色就放什么颜色盒子;两种情况取最大值即可
//样例通过,提交AC 2018-1-28 19:31
#include <stdio.h>
int main(){
    int r,b,c,d,e,ans1,ans2;
    scanf("%d%d%d%d%d",&r,&b,&c,&d,&e);
    ans1=r*c+b*d;
    if(r<b)ans2=r*e*2+(b-r)*d;
    else ans2=b*e*2+(r-b)*c;//r>=b
    printf("%d",ans1>ans2?ans1:ans2);
    return 0;
}

//P1851 好朋友
//在考虑约束是否包括1,经程序验证,发现包括1
//测试了18000 发现要超时,怎么办,先提交试试
//提交发现 测试点2 TLE 测试点3-5 ,9 WA
//看来是要采用技巧
//翻看讨论https://www.luogu.org/discuss/show?postid=3816
//找出序列号不小于 S 的第一对“非常好友”
//我一开始以为这句话是指A、B都不能小于S,结果一直WA,后来发现是指A不小于S就可以了,我真是醉的不要不要的。。。
//马上进行修改, if(a>=s){//此处写成 if(a>=s&&b>=s)
//提交,测试点4 WA
//https://www.luogu.org/problemnew/solution/P1851翻看题解,发现
//千万不要忘了不能使自己是自己的非常好友的情况,不可以!!!我因为这个错了好几次,就是A不了
//马上修改,if(a>=s&&a!=b){//此处写成if(a>=s)//此处写成 if(a>=s&&b>=s) 提交AC 2018-1-27 20:24
//该题的错误,发生在两点,一个是题目本身叙述有歧义,另一个是题目的叙述,没有往心里去。
#include <stdio.h>
int main(){
    int s,a,b,c,i;
    scanf("%d",&s);
    a=s;
    while(1){
        b=0;
        for(i=1;i<a;i++)
            if(a%i==0)b+=i;
        if(a>=s&&a!=b){//此处写成if(a>=s)//此处写成 if(a>=s&&b>=s)
            c=0;
            for(i=1;i<b;i++)
                if(b%i==0)c+=i;
            if(a==c){//判断是否互为好朋友
                printf("%d %d",a,b);
                break;
            }
        }
        a++;
    }
    return 0;
}

//P1146 硬币翻转
//模拟了样例,感觉以下输出是字典序最小
//0111
//1001
//0010
//1111
//题目描述感觉不对
//https://www.luogu.org/problemnew/solution/P1146看了题解,发现规律
//翻n次,翻到第i次时,i硬币不动,其他硬币翻转
//该题的思路,还是模拟,找规律
//该题的数学考点,取反。
//样例通过,提交AC 2018-1-29
#include <stdio.h>
#include <string.h>
int a[110];
int main(){
    int i,j,n;
    memset(a,0,sizeof(a));
    scanf("%d",&n);
    printf("%d\n",n);
    for(i=1;i<=n;i++){//第i次翻转
        for(j=1;j<=n;j++){//该次翻转对n枚硬币的处理
            if(j!=i)a[j]=!a[j];
            printf("%d",a[j]);
        }
        printf("\n");
    }
    return 0;
}
//P2415 集合求和
//研究 1 2 3 4
//子集[] [1] [2] [3] [4] [1 2] [1 3] [1 4] [2 3] [2 4] [3 4] [1 2 3] [1 2 4] [1 3 4] [2 3 4] [1 2 3 4]
//1*8+2*8+3*8+4*8=(1+2+3+4)*2^(4-1)
//发现规律 输入元素和*2^(n-1)
//样例通过,提交AC 2018-1-29 18:19
#include <stdio.h>
int main(){
    long long ans=0;
    int n=0,i,a;
    while(scanf("%d",&a)!=EOF)ans+=a,n++;
    for(i=1;i<n;i++)ans*=2;
    printf("%lld",ans);
    return 0;
}
//P1304 哥德巴赫猜想
//原以为写不出,硬着头皮,写着写着,发现样例通过,提交AC
//该题核心,质数判断。2018-1-29 18:46
#include <stdio.h>
int isPrime(int n){
    int i;
    if(n==1)return 0;
    if(n==2)return 1;
    for(i=2;i*i<=n;i++)
        if(n%i==0)return 0;
    return 1;
}
int main(){
    int n,i,j;
    scanf("%d",&n);
    for(i=4;i<=n;i+=2)
        for(j=2;j<=n/2;j++)
            if(isPrime(j)&&isPrime(i-j)){
                printf("%d=%d+%d\n",i,j,i-j);
                break;
            }
    return 0;
}
//P2043 质因子分解
//先算出N!必定溢出,int , long long都没用
//想看解答,但还是要自个尝试一次。
//第一步,找出N<=10000内的质数
//逆序,自N,N-1,N-2,...,2里查找相应的能被质数整除
//在枚举质数数组过程中,数据范围容易越界,在这个节骨眼上查了半个小时,排除之后,是坦途
//样例通过,提交AC 2018-1-30
//敢于尝试,很不不可能,自然而然 也就 变成了 可能
#include <stdio.h>
#include <string.h>
int cnt=0,a[10000],b[10000];//a[i]用来存储质数 b[i]用来计数质数a[i]的个数
int isPrime(int n){//0非质数 1质数
    int i;
    if(n==1)return 0;
    if(n==2)return 1;
    for(i=2;i*i<=n;i++)
        if(n%i==0)return 0;
    return 1;
}
void product_prime(int n){
    int i;
    for(i=2;i<=n;i++)
        if(isPrime(i))
            a[++cnt]=i;
}
void find_prime(int n){
    int i,j,k;
    for(i=n;i>=2;i--){
        k=i;
        for(j=1;j<=cnt&&a[j]<=k;j++)//此处写成 for(j=1;a[j]<=k;j++) 容易超出a[cnt] cnt范围 故,还需加j<=cnt的判定
            while(k%a[j]==0)b[j]++,k/=a[j];
    }
}
int main(){
    int n,i,j;
    memset(b,0,sizeof(b));
    scanf("%d",&n);
    product_prime(n);
    find_prime(n);
    for(i=1;i<=cnt;i++)
        if(b[i]!=0)
            printf("%d %d\n",a[i],b[i]);
    return 0;
}

//P2181 对角线
//画了图,研究了3 0;4 1;5 5;6 15
//但没什么收获,搜索网络,习得对角线边数n*(n-3)/2,还是无果,
//https://zhidao.baidu.com/question/1737606541030842707.html此文思路不错,摘抄如下:
//任取四个顶点,
//则四个顶点形成的四边形,
//对角线两两相交的交点仅有一个。
//另一方面,
//对角线两两相交的交点,
//对应着凸多边形的四个顶点。
//所以,对角线两两相交的交点的个数,
//等于从所有顶点里面取出四个的取法的数量,
//凸n边形(n≥4),有n个顶点,
//所以,对角线两两相交的交点的个数为
//C(n,4)=n(n-1)(n-2)(n-3)/24
//被usigned long long 输出格式所困扰,搜索,发现是%llu
//样例通过,提交,测试点3-7 WA
//ans=(unsigned long long)n*(n-1)/2*(n-2)/3*(n-3)/4;//此处写成 ans=n*(n-1)/2*(n-2)/3*(n-3)/4;
//请注意右边的强转
//提供一组测试数据1326 128231874225
//样例通过,提交AC 2018-2-1 18:48
//该题考点,排列组合,无符号长整数
#include <stdio.h>
int main(){
    int n;
    unsigned long long ans;
    scanf("%d",&n);
    ans=(unsigned long long)n*(n-1)/2*(n-2)/3*(n-3)/4;//此处写成 ans=n*(n-1)/2*(n-2)/3*(n-3)/4;
    printf("%llu",ans);
}


//P2651 添加括号III
//没有思路,
//https://www.cnblogs.com/war1111/p/7693485.html此文思路不错,摘抄如下:
//无论怎么添加,a2一定是分母,其他的可以是分子,所以最后看看,(a1*a3*..*an)%a2==0即可
//https://www.cnblogs.com/COLIN-LIGHTNING/p/8371664.html此文思路,代码都写得不错,思路摘抄如下:
//1.研读后我们发现,为了使其结果尽可能为整数,我们应使分母最大,分子最小;
//2.那么我们发现,a2无论如何都是在分母上的,那么我们这样添加括号即可:a1/(a2/a3/.../an)=a1a3...*an/a2,此时满足分母最大,分子最小;
//3.那么我们需要进行约分:对每一个分子都和分母求一次GCD,每次求后令分母除以GCD,到最后一项时若分母=1,则结果为整数;
//4.注意本题有多组数据;
//个人觉得,没有一定的数学嗅觉,该题想不出
//样例通过,提交AC 2018-2-1
#include <stdio.h>
int a[10100];
int gcd(int a,int b){//欧几里得算法 辗转相除法//要求a>b  
    if(b==0)return a;
    return gcd(b,a%b);
}
int main(){
    int t,n,i,j,min,max;
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        for(i=1;i<=n;i++)scanf("%d",&a[i]);
        if(a[2]>a[1])min=a[1],max=a[2];//找出a[1],a[2]中最大值,最小值
        else min=a[2],max=a[1];
        a[2]/=gcd(max,min);
        for(i=3;i<=n;i++){
            if(a[2]>a[i])min=a[i],max=a[2];//找出a[2],a[i]中最大值,最小值
            else min=a[2],max=a[i];
            a[2]/=gcd(max,min);
        }
        if(a[2]==1)printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}

//P1469 找筷子
//觉得下不了手,
//突发奇想,+一个-一个(即奇数位置的元素加,偶数位置的元素减),最后的答案,应是剩下的落单筷子长度
//样例通过,提交 测试点1-10 WA
//翻了下题解,发现,要将int 改成 long long ,对自己的算法,感觉没啥问题
//提交 测试点1-10 WA
//希望上述思路能找到一个反例,再开始其他思路
//1 3 1
//1-3+1=1
//刚在想,突然就发现一组反例,如上所示,真是,“众里寻他千百度,蓦然回首,那人却在,灯火阑珊处”
//采用异或思路,这么说吧,3^3=0; 3^3^3=3; 3^1^3=1;参考了题解https://www.luogu.org/problemnew/solution/P1469?page=2
//马上改算法。样例通过,提交AC 2018-1-30
#include <stdio.h>
int main(){
    int n,i,a,ans;
    scanf("%d",&n);
    scanf("%d",&ans);
    for(i=2;i<=n;i++){
        scanf("%d",&a);
        ans^=a;
    }
    printf("%d",ans);
    return 0;
}

//P1866 编号
//觉得水平还可以,没想到该题给了下马威,数学水平还需提高
//P1866 编号
//https://www.luogu.org/problemnew/solution/P1866稍微翻了下题解,立马明白该题意图
//只是没想到,与数学有关的 普及-难度 的题目,需要开始用到排序
//深深明白,小学奥数题难道博士生了。
//样例解释
//1-5 1-8 前者1-5中一定有1-8的元素,故1-8需扣除前面1位重复元素 5*(8-1)=35
//第一步,自小到大排序,第一个元素-0,第二个元素-1,第三个元素-2,依次类推,之后乘积即是答案
//样例通过,提交,测试点2,4-9 WA
//猜测,可能是int ans=1;溢出,改成long long ans=1;
//提交,AC 2018-1-30 20:58
#include <stdio.h>
#define Mod 1000000007
int a[60];
int main(){
    int n,i,j,t;
    long long ans=1;
    scanf("%d",&n);
    for(i=1;i<=n;i++)scanf("%d",&a[i]);
    for(i=1;i<=n;i++)//自小到大排序
        for(j=i+1;j<=n;j++)
            if(a[i]>a[j])t=a[i],a[i]=a[j],a[j]=t;
    for(i=1;i<=n;i++)
        ans=(ans*(a[i]-i+1))%Mod;
    printf("%lld",ans);
    return 0;
}

//P1107 最大整数
//所有数,先取出首位最大的,再取出第二位最大的,以此类推
//采用字符串的方式,进行处理
//提交,测试点5 WA
//提供两组输入数据
//输入:
//9 90 9
//输出:
//9990
//输入:
//4 45 454
//输出
//454544
//https://www.luogu.org/problemnew/solution/P1107翻了题解,发现,字符串比较函数,还是要自己编,不用系统的
//样例通过,提交AC 2018-1-31
#include <stdio.h>
#include <string.h>
char a[25][10],t[10],c[22],d[22];
int cmp(char a[],char b[]){
    strcpy(c,a),strcat(c,b);//c=a+b;
    strcpy(d,b),strcat(d,a);//d=b+a;
    if(strcmp(c,d)<0)return 1;//需要交换a,b;
    return 0;//无需交换a,b;
}
int main(){
    int n,i,j;
    scanf("%d",&n);
    for(i=1;i<=n;i++)scanf("%s",a[i]);
    for(i=1;i<=n;i++)//自大到小排序
        for(j=i+1;j<=n;j++)
            if(cmp(a[i],a[j])){//此处写成 strcmp(a[i],a[j])<0
                strcpy(t,a[i]);
                strcpy(a[i],a[j]);
                strcpy(a[j],t);
            }
    for(i=1;i<=n;i++)printf("%s",a[i]);
    return 0;
}

//P1706 全排列问题
//深搜,回溯算法
//样例通过,提交AC 2018-1-31
#include <stdio.h>
#include <string.h>
int n,vis[15],a[15];
void dfs(int step){
    int i,j;
    if(n+1==step){
        for(j=1;j<=n;j++)printf("%5d",a[j]);
        printf("\n");
        return ;
    }
    for(i=1;i<=n;i++)
        if(vis[i]==0){
            vis[i]=1;//设置
            a[step]=i;
            dfs(step+1);
            vis[i]=0;//恢复
        }
}
int main(){
    memset(vis,0,sizeof(vis));
    scanf("%d",&n);
    dfs(1);
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值