Bi-shoe and Phi-shoe
给出n个数字的序列a[],对于每个数字ai找到一个欧拉函数值大于等于ai的数bi,求找到的所有数bi的最小值之和sum
我们可以知道一个φ(p),如果p是一个素数的话,那么φ(p)=p-1;而对于所有小于p的值a,φ(a)<φ(p);这里我们知道φ(bi)>=ai;求bi的最小值,就只需要求出大于ai的第一个素数,将所有结果加和就可以了;
蒟蒻的代码烂死了
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
using namespace std;
const int inf =0x3f3f3f3f;
int p[1001000];
void Is_prime()
{
//mem(p,0);
p[1]=1;
for(int i=2;i<=1000;i++)
{
if(!p[i])
{
for(int j=2*i;j<1000000+100;j+=i)
{
p[j]=1;
}
}
}
}
int main()
{
Is_prime();
//cout<<p[2]<<p[3]<<endl;
int T,n,a,flag=1;
cin>>T;
long long ans,t;
while(T--)
{
ans=0;
cin>>n;
while(n--)
{
cin>>a;
for(int i=a+1;;i++)
if(p[i]==0)
{
ans+=i;
break;
}
}
printf("Case %d: %lld Xukha\n",flag,ans);
flag++;
}
}
观察σ(n)的每一项,发现每一项都像是一个等比数列的求和公式,将式子展开
可得到
求1-n这个值是个偶数,不太好求,所以转换思路求出奇数的个数,然后相减就可以了
只有所有项都是奇数的时候 该值就为奇数,可以知道,奇数的次方仍是奇数;
然每一个P都是素数,除了2以外的素数都是奇数
1——讨论Pi中不包含2的情况
这就要求e1,e2…ek都必须是偶数,才能保证每一项加和是奇数而
根据唯一分解定理表达式,每一项的e都是个偶数,所以每一个指数至少可以提出一个2,n=(剩余部分<一下用t代替>)^2;所以n至少是一个平方数(当然四次方,八次方也在其中);
2 ——Pi中包含2的情况假设就是第一项
那么pi==2的这一项不管e等于多少这一项一定是一个奇数
1该项的e=1
将这个2单独提出来n/2=(t)^2;所以n/2一个平方数;
2 e>=2时
同理化成n=(t)^2; n是一个平方数,
所以我们可以得到,如果σ(n)时一个技术的话,那么就有(n时一个平方数||n/2是一个平方数)
求1-n的σ(n)是奇数的个数,1-n平方数有sqrt(n)个,平方数的二倍有sqrt(n/2)个;
所以最终结果就是n-sqrt(n)-sqrt(n/2);
//传说中的推公式两小时,写代码1分钟;
int main()
{
int n;
ll a,b;
int flag=1;
ll ans=0;
cin>>n;
while(n--)
{
scanf("%lld",&a);
a-=((ll)sqrt(a)+(ll)sqrt(a/2));
printf("Case %d: ",flag);
flag++;
cout<<a<<endl;
}
}
Leading and Trailing
给定两个数n,k 求n^k的前三位和最后三位
ll qpow(ll a,ll b)
{
ll ans=1;
while(b)
{
if(b&1)
{
ans=(ans*a)%mod;
}
a=(a*a)%mod;
b/=2;
}
return ans;
}
int main()
{
ll ans,n,a,ant,T;
cin>>T;
int flag=1;
while(T--)
{
cin>>a>>n;
ant=qpow(a,n);//快速幂取模求前三位
ans = (ll)pow( 10.0 , 2 + fmod(n*log10(a) , 1) );//fmod函数的使用
while(ans >= 1000) ans /= 10;
printf("Case %d: ",flag);
flag++;
printf("%03lld %03lld\n",ans,ant);
}
}
Goldbach`s Conjecture
T组询问,每组询问是一个偶数n
验证哥德巴赫猜想
回答n=a+b
且a,b(a<=b)是质数的方案个数
欧拉筛打表到1e7,然后暴力跑n/2;判断是否是素数就可以,
#define MAX_N 10000000
int prime[MAX_N/10];
bool is_prime[MAX_N+1];
void sieve(int n)
{
int p=0;
//memset(is_prime,true,sizeof(is_prime));
is_prime[0] = is_prime[1] = 1;
for(int i = 2; i <= n/2; i++)
{
if(!is_prime[i])
prime[p++] = i;
for(int j=0; j<p && prime[j]*i<=n; j++)
{
is_prime[prime[j]*i]=1;
if(i%prime[j]==0)
break;
}
}
}
int main()
{
sieve(MAX_N);
// cout<<prime[1];
int T,n,ans,flag=1;
cin>>T;
//cout<<cnt<<endl;
while(T--)
{
ans=0;
n=read();
for(int i=0;prime[i]<=(n/2);i++)
{
if(is_prime[n-prime[i]]==0)
ans++;
}
printf("Case %d: %d\n",flag,ans);
flag++;
}
}
Harmonic Number (II)
求(n/1,n/2…n/n),数据范围是n<2^31,暴力求解肯定行不通;
这是一个n/x的求和,反比例函数图像
根据图像可以看出该图像关于y=x对称,交点为sqrt(x),所以只需要算到sqrt(x)在乘以2,就可以得到所有的和,然后注意sqrt(x)点计算了两次,需要减去一次
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<queue>
#include<stack>
#include<map>
using namespace std;
const int inf =0x3f3f3f3f;
const int maxn=5e5+5;
const int mod =9999991;
#define PI 3.14159265358979323846
#define ll long long
#define ull unsigned ll
#define DB double
inline int read()
{
int x=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s<='9'&&s>='0'){x=x*10+s-'0';s=getchar();}
return x*f;
}
long long H( int n,int m )
{
long long res = 0;
for( int i = 1; i <= n; i++ )
res = res + m / i;
return res;
}
int main()
{
int T;
ll a,b,ans,flag=1;
cin>>T;
while(T--)
{
cin>>a;
b=(int)sqrt(a);
//cout<<b<<endl;
ans=H(b,a);
//cout<<ans<<endl;
ans*=2;
ans-=b*b;
printf("Case %d: ",flag) ;
flag++;
cout<<ans<<endl;
}
}
Harmonic Number L
看到这个第一时间想到了调和级数,然后开始百度求和公式
其中Can=0.57721566490153286060651209 ;
由于Can的精度问题,该公式并无法算出准确值,所以当数较小时,可以打表直接计算,数大时再进行公式计算亲测错了好多遍,前面达表到1e5才过的
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<queue>
#include<stack>
#include<map>
using namespace std;
const int inf =0x3f3f3f3f;
const int maxn=1e5+5;
const int mod=1e9+7;
#define PI 3.14159265358979323846
#define ll long long
#define ull unsigned ll
#define Can 0.57721566490153286060651209
#define DB double
inline int read()
{
int x=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s<='9'&&s>='0'){x=x*10+s-'0';s=getchar();}
return x*f;
}
double a[maxn];
void f()
{
double res=1;
for(int i=1;i<=1e6;i++)
{
a[i]=a[i-1]+(res/(1.0*i));
}
}
int main()
{
f();
int T;
cin>>T;
int s;
int flag=1;
while(T--)
{
cin>>s;
printf("Case %d: ",flag);
flag++;
if(s<=1000000)
printf("%.10lf\n",a[s]);
else
printf("%.10lf\n",Can+log(s)+1.0/(2*s));
}
}