洛谷 简单数学问题

火星人
给出一个N个数的排列,求比它大M的排列
解法:stl

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

int a[10005];
int main()
{
    int n,m;cin>>n>>m;
    int k=0;
    for(int i=0;i<n;i++) cin>>a[i];
    do{
        if(k==m)break;
        k++;
    }while(next_permutation(a,a+n));
    for(int i=0;i<n;i++) cout<<a[i]<<" ";
}

麦森数****
计算(2^p)-1的位数 和 输出后五百位//p<310 0000
分析:位数与2^p相同,为 p*lg(2)+1 //证明心里懂
后五百位,快速幂+高精度

#include<bits/stdc++.h>
using namespace std;
typedef long long ElementType;

void multi(ElementType a[],ElementType b[])
{
    ElementType c[6000]={0};
    c[0]=a[0]+b[0];
    if(c[0]>500) c[0]=500;
    for(int i=0;i<a[0];i++)
    {
        for(int j=0;j<b[0];j++)
        {
            c[i+j+1]+=a[i+1]*b[j+1];
            if(c[i+j+1]>=10)
            {
                c[i+j+2]+=c[i+j+1]/10;
                c[i+j+1]%=10;
            }
        }
    }
    for(int i=0;i<=c[0];i++) a[i]=c[i];
}

int main()
{
    int p;cin>>p;
    cout<<(int)(p*log10(2)+1)<<endl;
    ElementType ans[3000]={0},b[3000]={0};//ans保存最终答案,b为幂次
    ans[0]=b[0]=1; ans[1]=1,b[1]=2;
    while(p>0)
    {
        if(p&1) multi(ans,b);
        multi(b,b);
        p>>=1;
    }
    ans[1]--;
    int k=500;
    for(int i=0;i<10;i++)
    {
        for(int j=0;j<50;j++)
        {
            cout<<ans[k--];
        }
        cout<<endl;
    }
}

约数研究*
求[1,n]内 所有数的约数的个数 之和
易知,[1,n]中的每个数i,在[1,n]中,作为约数的次数为n/i
所有ans=sigma(n/i);//i为[1,n];

看了大佬解法,才意识到 对于[1,n]中连续的一段,他们n/i的值是一样,计算也是重复的
那就让i 每次都跳到 n/j = n/i + 1的地方

#include<bits/stdc++.h>
using namespace std;

int main()
{
    int ans=0;
    int n,i,j;
    cin>>n;
    for(i=1;i<=n;i=j+1)
    {
        j=n/(n/i);
        ans+=(n/i)*(j-i+1);
    }
    cout<<ans<<endl;
}

负数进制转换*****
十进制数N 进制数-R
如果进制数是正数:日常操作就是 ans=N%R N/=R
但是如果R是负数,对于C++,ans=-5%-2=-1;所以要做处理

#include<bits/stdc++.h>
using namespace std;

void trans_num(int n,int b,char ans[])
{
    int _id=0,k;
    while(n!=0)
    {
        k=n%b;
        n/=b;
        if(k<0)//余数是负数
        {
            k-=b;//余数变成正数
            n++;//借位
        }
        if(k>=10) ans[_id]='A'-10+k;
        else ans[_id]='0'+k;
        _id++;
    }
    for(int i=_id-1;i>=0;i--)
        cout<<ans[i];
}

int main()
{
    int n,b;
    char ans[4000];
    cin>>n>>b;
    cout<<n<<"=";
    if(n==0)cout<<"0";
    else trans_num(n,b,ans);
    cout<<"(base"<<b<<")";
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值