【luogu】tg? 数学(未完

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

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

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

勾股方程的所有解:

\(x=d\frac{v^2-u^2}{2},y=duv,r=d\frac{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\n", ans * 4 + 4);
    return 0;
}

不定方程

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

求不定方程

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

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

对于 \(100\%\) 的数据,保证\(1 \le n\le 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\to $

\(\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<n\le 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\n", ans);
    for (int i = 1; i <= m; i++)
        if (!b[i])
            printf("%d\n", i);
}

P5020 货币系统(猜结论)

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

在一个完善的货币系统中,每一个非负整数的金额 \(x\) 都应该可以被表示出,即对每一个非负整数 \(x\),都存在 \(n\) 个非负整数 \(t[i]\) 满足 \(a[i] \times 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, 1\leq n\leq100,1\leq 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\n", 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\times2\times\cdots\times n\);特别地,定义 \(0!=1\)

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

对于 \(100\%\) 的数据,\(n\leq2000,m\leq2000,k\leq21,t\leq10^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\n",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\)

先筛出\(1\sim 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

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

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

\(\begin{align*}N=\Pi_i\ P_i^{\alpha _i}\end{align*}\) 正约数个数\(\begin{align*}=\Pi_i (\alpha _i+1)\end{align*}\) 正约数和\(\begin{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]圆上整点

\(\begin{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\ \therefore A\not=B\)\(A,B\)本身一定为完全平方数

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

\(\because A\not=B\ \therefore a\not=b\)\(a<b\) 所以\(a*a=\frac{r-x}d,b*b=\frac{r+x}d\to a^2+b^2=\frac{2r}d\)

通解:\(x=d\frac{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的同余方程\(ax\equiv 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)\not=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\n", ans);
    for (int i = 1; i <= m; i++)
        if (!b[i]) printf("%d\n", i);
}

Vijos1915 解方程加强版

不想搞了==

小凯的诱惑

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

我还是喜欢摸鱼==

posted @ 2019-10-24 22:03  委屈的咸鱼鱼鱼鱼  阅读(175)  评论(0编辑  收藏  举报