火星人
给出一个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<<")";
}