【luogu】tg? 数学(未完

*P2508 [HAOI2008]圆上的整点(勾股方程结论)

求一个给定的圆((x^2+y^2=r^2)),在圆周上有多少个点的坐标是整数。

对于 (100\%) 的数据,(n<=2000 000 000)

勾股方程的所有解:

(x=dfrac{v^2-u^2}{2},y=duv,r=dfrac{v^2+u^2}2)

所以我们只要轻易地枚举(2r)的因子(d),对于每个(d)我们用(O(sqrt{frac{r}{d}}))的时间枚举(u),代入(r)的计算式得出(v^2)计算(v^2)是否为完全平方数及(u)(v)是否互质

这样可以枚举出一个象限内的整点个数 然后输出((ans+1)∗4)即可

复杂度O(轻松跑得过)

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
LL r, ans;
LL gcd(LL x, LL y) { return y ? gcd(y, x % y) : x; }
bool check(LL u, LL V)
{
    int v = LL(sqrt(V));
    if (V == v * v)
        return gcd(u, v) == 1;
    return 0;
}
LL calc(LL x)
{
    LL tmp = 0;
    for (LL u = 1; u * u * 2 < x; u++)
        tmp += check(u, x - u * u);
    return tmp;
}
int main()
{
    scanf("%lld", &r);
    for (LL d = 1; d * d <= 2 * r; d++)
        if (2 * r % d == 0)
            ans += calc(2 * r / d) + (d * d == 2 * r ? 0 : calc(d));
    printf("%lld
", ans * 4 + 4);
    return 0;
}

不定方程

*P4167 [Violet]樱花(签到题)

求不定方程

[frac{1}{x} + frac{1}{y} = frac{1}{n!} ]

的正整数解(x,y)的数目。

对于 (100\%) 的数据,保证(1 le nle 10^6)

变形((x-n!)(y-n!)=(n!)^2)

由一一对应关系可以知道解的数目等于((n!)^2)的约数个数

(n!)好大,但是明显质因子不超过n,用约数个数公式即可

#include<bits/stdc++.h>
#define maxn 1000010
#define mod 1000000007
using namespace std;
int prime[maxn],vis[maxn],tot,n;
long long ans=1,tmp,x,y;
int main()
{
	for(int i=2;i<=maxn;i++)
	{
		if(!vis[i])prime[tot++]=i;
		for(int j=0;j<tot&&prime[j]*i<maxn;j++)
		{
			vis[prime[j]*i]=1;
			if(i%prime[j]==0)break;
		}
	}
	scanf("%d",&n);
	for(int i=0;prime[i]<=n;i++)
	{
		tmp=0;x=n;y=prime[i];
		for(;x;x/=prime[i])
			tmp+=x/y;
		ans=(ans*(tmp<<1|1)%mod)%mod;
	}
	printf("%d",ans);
}

P1835 素数的密度

P3601 签到题

UOJ

4167

(frac1x+frac1y=frac1{n!})

$(x+y)n!=xy o $

(sum frac n{p^k}) (126!)末尾多少个0 5的倍数贡献多少 (5*25+25*5+125*1)

2508 圆上的整点

P2312 解方程(大整数取模)

已知多项式方程:

[a_0+a_1x+a_2x^2+cdots+a_nx^n=0 ]

求这个方程在 ([1,m]) 内的整数解((n)(m) 均为正整数)。

对于 (100\%) 的数据:(0<nle 100,|a_i|le 10^{10000},a_n≠0,m<10^6)

#include <bits/stdc++.h>
using namespace std;
#define maxn 1000010
typedef long long LL;
LL a[110][4], mod[4] = {10007, 11003, 12007, 13001};
int b[maxn], n, m;
string qwq;
bool check(LL x)
{
    for (int k = 0; k < 4; k++)
    {
        LL tmp = a[n][k];
        for (int i = n - 1; i >= 0; i--)
            tmp = (tmp * x + a[i][k]) % mod[k];
        if (tmp)
        {
            for (int i = x; i <= m; i += mod[k])
                b[i] = 1;
            return 0;
        }
    }
    return 1;
}
int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 0; i <= n; i++)
    {
        cin >> qwq;
        for (int k = 0; k < 4; k++)
        {
            LL flg = 1, tmp = 0;
            for (int j = 0; j < qwq.length(); j++)
                if (qwq[j] == '-')
                    flg = -1;
                else
                    tmp = (tmp * 10 + qwq[j] - 48) % mod[k];
            a[i][k] = tmp * flg;
        }
    }
    int ans = 0;
    for (int x = 1; x <= m; x++)
        if (!b[x] && check(x))
            ans++;
    printf("%d
", ans);
    for (int i = 1; i <= m; i++)
        if (!b[i])
            printf("%d
", i);
}

P5020 货币系统(猜结论)

在网友的国度中共有 (n) 种不同面额的货币,第 (i) 种货币的面额为 (a[i]),你可以假设每一种货币都有无穷多张。为了方便,我们把货币种数为 (n)、面额数组为 (a[1..n]) 的货币系统记作 ((n,a))

在一个完善的货币系统中,每一个非负整数的金额 (x) 都应该可以被表示出,即对每一个非负整数 (x),都存在 (n) 个非负整数 (t[i]) 满足 (a[i] imes t[i]) 的和为 (x)。然而, 在网友的国度中,货币系统可能是不完善的,即可能存在金额 (x) 不能被该货币系统表示出。例如在货币系统 (n=3), (a=[2,5,9]) 中,金额 (1,3) 就无法被表示出来。

两个货币系统 ((n,a))((m,b)) 是等价的,当且仅当对于任意非负整数 (x),它要么均可以被两个货币系统表出,要么不能被其中任何一个表出。

现在网友们打算简化一下货币系统。他们希望找到一个货币系统 ((m,b)),满足 ((m,b)) 与原来的货币系统 ((n,a)) 等价,且 (m) 尽可能的小。他们希望你来协助完成这个艰巨的任务:找到最小的 (m)

对于 (100\%) 的数据,满足 (1 ≤ T ≤ 20, 1leq nleq100,1leq a[i] leq25000)

#include <bits/stdc++.h>
using namespace std;
#define maxv 25010
#define maxn 110
int T, n, a[maxn];
bitset<maxv> v;
int main()
{
    for (scanf("%d", &T); T; T--)
    {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++)
            scanf("%d", a + i);
        sort(a + 1, a + 1 + n);
        v.reset();
        v[0] = 1;
        int tmp = 0;
        for (int i = 1; i <= n; i++)
            if (!v[a[i]])
            {
                tmp++;
                for (int w = a[i]; w <= a[n]; w <<= 1)
                    v |= v << w;
            }
        printf("%d
", tmp);
    }
}

poi sums

P2822 组合数问题(签到题)

组合数 (C_n^m) 表示的是从 (n) 个物品中选出 (m) 个物品的方案数。举个例子,从 ((1,2,3)) 三个物品中选择两个物品可以有 ((1,2),(1,3),(2,3)) 这三种选择方法。根据组合数的定义,我们可以给出计算组合数 (C_n^m) 的一般公式:

[C_n^m=frac{n!}{m!(n-m)!} ]

其中 (n!=1 imes2 imescdots imes n);特别地,定义 (0!=1)

小葱想知道如果给定 (n,m)(k),对于所有的 (0leq ileq n,0leq jleq min left ( i, m ight )) 有多少对 ((i,j)) 满足 (C_i^j)(k) 的倍数。

对于 (100\%) 的数据,(nleq2000,mleq2000,kleq21,tleq10^4)

离线+前缀和

#include<bits/stdc++.h>
#define maxn 2010
using namespace std;
#define G c=getchar()
inline int read()
{
    int x=0,f=1;char G;
    for(;'0'>c||c>'9';G)if(c=='-')f=-1;
    for(;'0'<=c&&c<='9';G)x=10*x+c-48;
    return x*f;
}
int s[maxn][maxn],c[maxn][maxn],D=-1,d[2],g[2],K,T;
int main()
{
    T=read(),K=read();
    for(int i=0;i<=2000;i++)
        s[i][0]=c[i][0]=1;
    for (int i = 1; i <= 2000; i++)
        for (int j = 1; j <= i; j++)
            c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % K;
    for(int i=1;i<=2000;i++)
        for(int j=1;j<=2000;j++)
            s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+(c[i][j]==0&&i>=j);
    for(int n,m;T--;)
        n=read(),m=read(),printf("%d
",s[n][m]);
    return 0;
}

4071

P1835

给定区间[L,R](L≤R≤2147483647,R-L≤1000000),请计算区间中素数的个数。

可以发现(L,R)范围大但差值小

理论上利用(sqrt{2147483647}le50000)的质数就可以筛出来题目范围内的素数

所以筛完素数后再重新筛一遍就好了

int cnt=0,ans=0,prime[50000];bool v[50010];
void primes(){
	for(int i=2;i<=50000;++i){
		if(!v[i]) v[i]=1,prime[++cnt]=i;
		for(int j=1;j<=cnt&&i*prime[j]<=50000;++j){
			v[i*prime[j]]=1;
			if(!(i%prime[j])) break;
		}
	} 
}

bool a[N];
int main(){
#ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
#endif
	primes();
	rd(l),rd(r);
	for(int i=1;(ll)prime[i]*prime[i]<=r&&i<=cnt;++i)
		for(ll j=max(2ll,(l-1)/prime[i]+1)*prime[i];j<=r;j+=prime[i])
		a[j-l]=1;
	for(ll i=l;i<=r;++i) if(!a[i-l]) ++ans;
	printf("%d",ans);
    return 0;
}

P3601

我们定义一个函数:qiandao(x)为小于等于x的数中与x不互质的数的个数。

这题作为签到题,给出l和r,要求求(sum_{i=l}^rqiandao(i)~mod~666623333)

(1 leq l leq r leq 10^{12},r-l leq 10^6)

先筛出(1sim 10^6)内的素数 然后利用埃氏筛来搞一遍欧拉函数就行

要特判大于平方根的因子

int cnt=0,prime[N];bool v[N];
void primes(){
    for(int i=2;i<=1000000;++i){
        if(!v[i]) v[i]=1,prime[++cnt]=i;
        for(int j=1;j<=cnt&&i*prime[j]<=1000000;++j){
            v[i*prime[j]]=1;
            if(!(i%prime[j])) break;
        }
    }
}
void Mod(ll &x){x>P?x%=P:x;}
int main(){
#ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
#endif
	primes();
	rd(l),rd(r);
	for(ll i=l;i<=r;++i)  phi[i-l]=K[i-l]=i;
	for(int i=1;i<=cnt;++i)
		for(ll p=prime[i],j=max(2ll,(l-1)/p+1)*p;j<=r;j+=p){
			phi[j-l]=phi[j-l]/p*(p-1);
			while(!(K[j-l]%p)) K[j-l]/=p;
		}
	for(ll i=l;i<=r;++i){
		if(K[i-l]!=1) phi[i-l]=phi[i-l]/K[i-l]*(K[i-l]-1);
		ans+=i-phi[i-l],Mod(ans);
	}
	printf("%lld",ans);
    return 0;
}

UOJ48 核聚变反应强度

求第二大的公约数

从小到大用(a_1)试除(gcd)

ll gcd(ll x,ll y){return !y?x:gcd(y,x%y);}
int main(){
#ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
#endif
	rd(n),rd(a),b=a;
	for(int i=2;(ll)i*i<=b;++i)
	if(!(b%i)){
		p[++p[0]]=i;
		while(!(b%i)) b/=i;
	}
	if(b!=1)  p[++p[0]]=b;
	printf("%lld ",p[1]!=a?a/p[1]:1);
	for(int i=2,j;i<=n;++i){
		rd(b);
		c=gcd(a,b);
		for(j=1;j<=p[0];++j) if(!(c%p[j])) break;
		if(j>p[0]) printf("-1 ");
		else printf("%lld ",c/(ll)p[j]);
	}
    return 0;
}

P4167

(egin{align*}frac1x+frac1y=frac1{n!}end{align*})

((x+y)n!=xy o (x-n!)(y-n!)=(n!)^2) 一一对应可得 解数目等于((n!)^2)的约数个数 用约束个数公式

(egin{align*}N=Pi_i P_i^{alpha _i}end{align*}) 正约数个数(egin{align*}=Pi_i (alpha _i+1)end{align*}) 正约数和(egin{align*}=Pi_i (Sigma_{j=0}^{alpha_i}(P_i)^j)end{align*})

(n!)的质因数只会(le n) 对于(n)的一个质因子(p)(n!)中的个数为(n/p+n/p^2+...+n/p^k)

int cnt=0,prime[N];bool v[N];
void primes(){
	for(int i=2;i<=n;++i){
		if(!v[i]) v[i]=1,prime[++cnt]=i;
		for(int j=1;j<=cnt&&i*prime[j]<=n;++j){
			v[i*prime[j]]=1;
			if(!(i%prime[j])) break;
		}
	}
}
void Mod(ll &x){x<P?x:x%=P;}
int main(){
#ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
#endif
	rd(n);
	primes();
	for(int i=1,x,p;i<=cnt;++i){
		x=n,p=prime[i],ret=0;
		while(x) ret+=(ll)x/p,x/=p;
		ans*=(ret<<1|1),Mod(ans);
	}
	printf("%lld",ans);
    return 0;
}

[HAOI2008]圆上整点

(egin{align*}x^2+y^2&=r^2\y^2&=r^2-x^2\y&=sqrt{(r+x)(r-x)}end{align*}) 令:(d=gcd(r+x,r-x)),则:设(A=frac{r-x}d,B=frac{r+x}d) 因为(d)(r+x,r-x)的最大公约数 所以一定存在(gcd(A,B)=1,A,B)互质

(A,B)代回柿子 得:(y^2=d^2*A*B) 因为(d^2,y^2)为完全平方数 则(A*B)一定为完全平方数 又(gcd(A,B)=1 herefore A ot=B)(A,B)本身一定为完全平方数

(A)的算术平方根为(a)(B)的算术平方根为(b) 即:(A=a*a,B=b*b)

(ecause A ot=B herefore a ot=b)(a<b) 所以(a*a=frac{r-x}d,b*b=frac{r+x}d o a^2+b^2=frac{2r}d)

通解:(x=dfrac{v^2-u^2}2,y=duv,r=frac{2(v^2+u^2)}2)

枚举(2r)的因子(d),对于每个(d)(O(sqrt{frac rd}))枚举(u),带入(r)计算出(v^2) 计算(v^2)是否为完全平方数及(i,v)是否互质

ll gcd(ll a,ll b){return !b?a:gcd(b,a%b);}
bool check(ll a,ll b){
	ll x=(ll)sqrt(b);
	if(x*x==b) return gcd(a,b)==1;
	return 0;
}
ll calc(ll d){
	ll ret=0;
	for(ll a=1;(a*a<<1)<d;++a)
	ret+=check(a,d-a*a);
	return ret;
}
int main(){
#ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
#endif
	rd(r),r<<=1;
	for(ll d=1;d*d<=r;++d)
	if(!(r%d)) ans+=calc(d)+(((d*d)==r)?0:calc(r/d));
	printf("%lld",ans);
    return 0;
}

P1082同余方程(review)
扩欧 求关于x的同余方程(axequiv 1(mod b)) 的最小正整数解

void exgcd(ll a,ll b,ll &x,ll &y){
    if(!b){x=1,y=0;return;}
    exgcd(b,a%b,x,y);
    ll t=x;x=y,y=t-(a/b)*y;
}
void exgcd(int a,int b,int &d,int &x,int &y){
    if(b) exgcd(b,a%b,d,y,x),y-=x*(a/b);
    else d=a,x=1,y=0;
}

P2312 解方程(新姿势)

已知多项式方程:(a_0+a_1x+a_2x^2+cdots+a_nx^n=0) 求这个方程在([1,m])内的整数解((n)(m)均为正整数

选几个较大素数

对于每个(x)算出(f(x)\%p_i)(f(x)=0)(f(x)\%p_i)必然等于0 多选几个素数 在一定范围内可判断成功

(f(x+p)equiv f(x)(mod p)) 对于一个(x),(f(x) ot=0(mod p)),则(x+p,x+2p...)均不为方程的解

懒得再打一遍了==

typedef long long LL;
LL a[110][4], mod[4] = {10007, 11003, 12007, 13001};
int b[maxn], n, m;
string qwq;
bool check(LL x){
    for (int k = 0; k < 4; k++){
        LL tmp = a[n][k];
        for (int i = n - 1; i >= 0; i--) tmp = (tmp * x + a[i][k]) % mod[k];
        if (tmp){
            for (int i = x; i <= m; i += mod[k]) b[i] = 1;
            return 0;
        }
    }
    return 1;
}
int main(){
    scanf("%d%d", &n, &m);
    for (int i = 0; i <= n; i++){
        cin >> qwq;
        for (int k = 0; k < 4; k++){
            LL flg = 1, tmp = 0;
            for (int j = 0; j < qwq.length(); j++)
                if (qwq[j] == '-') flg = -1;
                else tmp = (tmp * 10 + qwq[j] - 48) % mod[k];
            a[i][k] = tmp * flg;
        }
    }
    int ans = 0;
    for (int x = 1; x <= m; x++)
        if (!b[x] && check(x)) ans++;
    printf("%d
", ans);
    for (int i = 1; i <= m; i++)
        if (!b[i]) printf("%d
", i);
}

Vijos1915 解方程加强版

不想搞了==

小凯的诱惑

(ax+by=c)同解为(x=x_0+bt,y=y_0-at)

我还是喜欢摸鱼==

原文地址:https://www.cnblogs.com/lxyyyy/p/11735288.html