*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]樱花(签到题)
求不定方程
的正整数解(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 解方程(大整数取模)
已知多项式方程:
求这个方程在 ([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) 的一般公式:
其中 (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)
我还是喜欢摸鱼==