• 完全平方数、樱花两个简单数论题


    Description
    给你一个数字N,希望在[1..N]之间找出数字x,y,满足下列条件

    1<=x,y<=N,并且x * x-y是个完全平方数,0也算是完全平方数

    问能找出多少对(x,y)来,输出结果%998244353

    Format
    Input
    第一行给出N

    N<=1e12

    Output
    如题,输出结果%998244353.

    Samples
    输入数据 1
    3
    输出数据 1
    2
    输入数据 2
    10
    输出数据 2
    8
    输入数据 3
    10000000000
    输出数据 3
    52583544
    Hint

    对于样例来说

    xx=1,yy=1

    xx=2,yy=3

    求x^2-y=z^2

    这个式子不好变形,所以换一下,变成

    x^2-z^2=y
    于是(x+z)(x-z)=y
    简化一下
    令p=x+z,q=x-z,于是x=(p+q)/2,z=(p-q)/2,y=pq
    于是p*q=y,因为1<=y<=N
    于是p*q<=N
    易知
    p>=q
    于是q<=sqrt(n).于是枚举q,然后p=n/q,注意此时的p是有这么多选择的,其值不唯一


    由x=(p+q)/2,可知p,q必须是同奇同偶,只有这样才能得到x

    于是问题转化成

    对于一个数列,以q开头,公差为2,最后一个数字的值不超过p.现需统计这个数列共有多少项

    于是q+(项数-1)*2<=p

    于是项数<=(p-q)/2+1

    总结:这类题都是通过数学变换,找到某个数字的范围,然后进行枚举

    #include <bits/stdc++.h>
    using namespace std;
    const int mod=998244353;
    
    int main()
    {
        long long n;
        cin>>n;
        long long sum=0;
        //x*x-y*y=z...(x+y)(x-y)=z
    	//p为x+y,q为x-y. 
        //p*q<=n,p>=q
        //p,q同奇同偶 
        for(long long i=1;i*i<=n;i++)
        {
            long long j=n/i;
            long long s=(j-i)/2+1;
    		sum=(sum+s)%mod; 
        }
        cout<<sum%mod<<endl;
        return 0;
    }
    

      

    樱花

    Description
    给定数字N,有多少正整数对(x,y)满足1/x+1/y=1/N!

    Format
    Input
    一个正整数N,N<=1000000

    Output
    一个整数并对10^9+7取模

    Samples
    输入数据 1
    2
    输出数据 1
    3
    hint //有三个整数对(3,6),(4,4),(6,3)满足题意

    给定数字N,有多少正整数对(x,y)满足1/x+1/y=1/N!
    输入格式
    一个正整数N,N<=1000000
    输出格式
    一个整数,如上所述,对10^9+7取模
    样例输入
    2
    样例输出
    3
    //有三个整数对(3,6),(4,4),(6,3)满足题意


    题解:
    先令n! = a:
    1 / x + 1 / y = 1 / a  =>  x = y * a / (y - a)
    再令 k = y - a:
    于是x = a + a ^ 2 / k  =>  k | a ^ 2
    我们来看下样例是如何求出来的,明显a=2
    故当K=1时,x=2+4/1=6
    故当K=2时,x=2+4/2=4
    故当K=4时,x=2+4/4=3
    因而此题只需要对N!^2,进行约数分解就好了。

    #include<iostream>
    #include<cstdio>
    using namespace std;
    #define MAX 1000100
    #define MOD 1000000007
    int n,ans=1;
    bool zs[MAX];
    int main()
    {
        cin>>n;
        for(int i=2;i<=n;++i)
            if(!zs[i])
            {
                for(int j=i;j<=n/i;j++)
    			     zs[j*i]=true;
                int p=n,s=0;
                while(p)
    			   s=(s+p/i*2)%MOD,p/=i;
                ans=1ll*ans*(s+1)%MOD;
            }
        cout<<ans<<endl;
        return 0;
    }
    

      

    另一个较为少见的写法

    #include <cstdio>
    #define maxn 1000010
    #define mod 1000000007
    using namespace std;
    long long v[maxn], pri[maxn], cnt[maxn], d;
    inline void primes(long long n) 
    {
    	for(long long i = 2; i <= n; i++) 
    	{
    		if(!v[i]) 
    		   v[i] = i, pri[++d] = i;
    		for(long long j = 1; j <= d; j++) 
    		{
    			if(pri[j] * i > n || pri[j] > v[i]) 
    			    break;
    			v[pri[j] * i] = pri[j];
    		}
    	}
    }
    inline void eular(long long n) 
    {
    	while(n > 1) 
    	     cnt[v[n]]++, n /= v[n];
    }
    int main() {
    	primes(1000000);
    	long long n;
    	scanf("%lld", &n);
    	for(long long i = 1; i <= n; i++) 
    	    eular(i);
    	long long ans = 1;
    	for(long long i = 1; i <= d; i++) 
    	    if(cnt[pri[i]]) 
    		{
    			ans = ans * (cnt[pri[i]] * 2 % mod + 1) % mod;
    		}
    	printf("%lld\n", ans);
    	return 0;
    }
    

      

  • 相关阅读:
    oracle数据库版本进化的关键节点
    到底什么是数据库呢?
    迁移数据之后,读取数据库变得很慢
    为什么越来越多的人使用python呢?
    20135306 2.4 ELF文件格式分析
    20135306 2.3程序破解实践
    20135306黄韧模块实践报告
    Linux内核学习总结
    Linux内核分析期中知识点总结
    LINUX内核分析第八周学习总结——进程的切换和系统的一般执行过程
  • 原文地址:https://www.cnblogs.com/cutemush/p/16718410.html
Copyright © 2020-2023  润新知