zoukankan      html  css  js  c++  java
  • 【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)

    我还是喜欢摸鱼==

  • 相关阅读:
    monads-are-elephants(转)
    程序语言简史(转)
    语法的省略不能造成编译器的歧义
    scala getter and setter
    隐式类型转换
    java 调用 scala
    列表的操作
    Scala HandBook
    Scala 高级编程练习
    Net 2.0 C# 专用的只读类Tuple
  • 原文地址:https://www.cnblogs.com/lxyyyy/p/11735288.html
Copyright © 2011-2022 走看看