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; }