学习数学知识的一天
反素数
首先,该题数据范围较大,
1
0
9
10^9
109,因此不能朴素枚举,又因为相当于是求围内约数最多的数,可以想到:
n
=
2
a
×
3
b
…
…
n=2^a \times 3^b……
n=2a×3b……
然后就可以直接枚,最多也就枚到23就ok了,但是注意
另一种思路:
打表,咳咳,其实是认真的,因为只有前几个素数,范围较小,所以就直接打前几个反素数,然后观察规律,就可以发现是以差的倍数增加的,就可以先打小表再打大表:
#include <bits/stdc++.h>
#define ll long long
#define N 100
using namespace std;
ll n,ans;
int a[N]={1,2,4,6,12,24,36,48,60,120,180,240,360,720,840,1260,1680,2520,5040,7560,10080,15120,20160,25200,27720,45360,50400,55440,83160,110880,166320,221760,277200,332640,498960,554400,665280,720720,1081080,1441440,2162160,2882880,3603600,4324320,6486480,7207200,8648640,10810800,14414400,17297280,21621600,32432400,36756720,43243200,61261200,73513440,110270160,122522400,147026880,183783600,245044800,294053760,367567200,551350800,698377680,735134400,1102701600,1396755360};
int main()
{
scanf("%d",&n);
for(int i=N-1;i>=0;i--)
{
if(a[i]&&a[i]<n)
{
printf("%d\n",a[i]);
break;
}
}
return 0;
}
五指山
一看就知道是同余问题,所以反手打出exgcd的版,
不会扩展欧几里得的点这儿
后面判断一下就好了
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll T,a,b,x,y;
ll exgcd(ll a, ll b, ll & x, ll & y)
{
if (!b){
x = 1;
y = 0;
return a;
}
ll d = exgcd(b, a % b, y, x);
y -= a / b*x;
return d;
}
int main(){
scanf("%d",&T);
while(T--){
ll a,b,x,y,p,q;
scanf("%d%d%d%d",&b,&a,&x,&y);
ll g=exgcd(b,a,q,p);
if((y-x)%g){
printf("Impossible\n");
continue;
}
p*=(y-x)/g;
b/=g;
ll ans=(p%b+b)%b;
printf("%lld\n",ans);
}
return 0;
}
Xiao 9*大战朱最学
yes,模板题,中国剩余定理,然后就可以(也是exgcd)
直接干就完事
#include<bits/stdc++.h>
#define N 15
#define ll long long
using namespace std;
ll a[N], b[N];
ll M[N], k[N];
ll exgcd(ll a, ll b, ll& x, ll& y)
{
ll d = a;
if (!b){
x = 1,y = 0;
return a;
}
d = exgcd(b, a % b, y, x);
y -= (a / b) * x;
return d;
}
int main()
{
int n;
ll x, y, ans = 0, mod = 1;
cin >> n;
for (int i = 1; i <= n; i++){
cin >> a[i] >> b[i];
mod *= a[i];
}
for (int i = 1; i <= n; i++){
M[i]=mod/a[i];
exgcd(M[i],a[i],x,y);
k[i] = (a[i] + x % a[i]) % a[i];//保证x为正数
ans = (ans + b[i] * k[i] * M[i]) % mod;
}
printf("%lld",ans);
return 0;
}
Goldbach’s Conjecture
这属于是很难很难啊,都还没证明呢水题了,刚开始想暴力的然后……
算了,暴力不优雅。
就先预处理后直接从小往大枚,然后就没事了
写个primes的代码练练手就好了
void pre(LL n){
memset(v,0,sizeof(v));
m=0;
for(LL i=2; i<=n; i++) {
if(v[i]==0) {
v[i]=i;
prime[++m]=i;
}
for(LL j=1; j<=m; j++) {
if(prime[j]>v[i] || prime[j]>n/i)break;
v[i*prime[j]]=prime[j];
}
}
// for(int i=1;i<=m;i++)printf("%d\n",prime[i]);
}
溜了溜了