gcd&exgcd&crt&excrt

22 篇文章 0 订阅
3 篇文章 0 订阅

HDU 5512

/*根据gcd(a,b)=gcd(a,a-b)可知,gcd(a,b)一定在最后的集合中
设d=gcd(a,b),则小于等于n的所有d的倍数均可以得到,
且不为d的倍数的均得不到*/
#include<bits/stdc++.h>
using namespace std;
int T,a,b,n,i,ans;
int main(){
	scanf("%d",&T);
	for (i=1;i<=T;i++){
		scanf("%d%d%d",&n,&a,&b);
		ans=n/__gcd(a,b);
		printf("Case #%d: %s\n",i,ans&1?"Yuwgna":"Iaka");
	}
}

pku2115(important)

#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
ll a,b,c,k,t,x,y;
ll ex_gcd(ll a,ll b,ll &x,ll &y){
	if (!b){
		x=1,y=0;
		return a;
	}
	ll t=ex_gcd(b,a%b,y,x);
	y-=a/b*x;
	return t;
}
int main(){
	while (~scanf("%lld%lld%lld%lld",&a,&b,&c,&k)){
		if (!a && !b && !c && !k) return 0;
		k=1ll<<k;
		if ((b-a)%__gcd(c,k)!=0) puts("FOREVER");
		else{
			t=ex_gcd(c,k,x,y);
			x=x*((b-a)/t)%k;
			x=(x%(k/t)+k/t)%(k/t);//很重要
			printf("%lld\n",x);
		}
	}
}

pku2891(excrt模板)

#include<cstdio>
using namespace std;
typedef long long ll;
int n,i,fl;
ll n1,a1,n2,a2,c,gcd,x,y,t;
ll ex_gcd(ll a,ll b,ll &x,ll &y){
	if (!b){
		x=1,y=0;
		return a;
	}
	ll t=ex_gcd(b,a%b,y,x);
	y-=a/b*x;
	return t;
}
int main(){
	while (~scanf("%d",&n)){
		scanf("%lld%lld",&n1,&a1);
		fl=0;
		for (i=1;i<n;i++){
			scanf("%lld%lld",&n2,&a2);
			if (fl) continue;
			c=a2-a1;
			gcd=ex_gcd(n1,n2,x,y);
			if (c%gcd){
				fl=1;puts("-1");
				continue;
			}
			x*=c/gcd;
			t=n2/gcd;
			x=(x%t+t)%t;
			a1+=x*n1;
			n1*=n2/gcd;
		}
		if (!fl) printf("%lld\n",a1);
	}
}

pku1006

//crt
#include<cstdio>
using namespace std;
int p,e,i,d,ca,n;
int main(){
	while(~scanf("%d%d%d%d",&p,&e,&i,&d) && p!=-1){
		n=(5544*p+14421*e+1288*i-d+21252-1)%21252+1;
		printf("Case %d: the next triple peak occurs in %d days.\n",++ca,n);
	}
}

HDU 5768 Lucky7 数论(含crt模板)

//https://blog.csdn.net/danliwoo/article/details/52058069
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll x,y,ans,l,r;
int n,m[16],a[16],s[16],cnt,tmp,i,T,j,ca;
ll mul(ll x,ll y,ll z){
	ll res=0;
	while (y){
		if (y&1) (res+=x)%=z;
		(x+=x)%=z;y>>=1;
	}
	return res;
}
ll calc(ll x,ll y,ll M){
	return (x-y)/M;
}
void ex_gcd(ll a,ll b,ll &x,ll &y){
	if (!b) x=1,y=0;
	else ex_gcd(b,a%b,y,x),y-=a/b*x;
}
ll crt(ll l,ll r){
	ll M=1,sum=0;
	for (int i=0;i<=n;i++)
		if (s[i]) M*=m[i];
	for (int i=0;i<=n;i++)
		if (s[i]){
			ll t=M/m[i];
			ex_gcd(t,m[i],x,y);
			x=(x%m[i]+m[i])%m[i];
			sum=(sum+mul(a[i]*t%M,x,M)%M+M)%M;
		}
	return calc(r+M,sum,M)-calc(l-1+M,sum,M);
}
int main(){
	scanf("%d",&T);
	while (T--){
		scanf("%d%lld%lld",&n,&l,&r);
		ans=0;
		m[n]=7;a[n]=0;s[n]=1;
		for (i=0;i<n;i++) scanf("%d%d",&m[i],&a[i]);
		for (i=0;i<1<<n;i++){
			tmp=i;cnt=0;
			for (j=0;j<n;j++) s[j]=tmp&1,cnt^=s[j],tmp>>=1;
			ans+=crt(l,r)*(cnt==0?1:-1);
		}
		printf("Case #%d: %lld\n",++ca,ans);
	}
}

HDU 1573 X问题(excrt模板)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int T,i,n,m,fl,a[11],b[11];
ll a1,a2,c,n1,n2,x,y,gcd,t;
ll ex_gcd(ll a,ll b,ll &x,ll &y){
	if (!b){x=1,y=0;return a;}
	ll r=ex_gcd(b,a%b,y,x);
	y-=a/b*x;
	return r;
}
int main(){
	scanf("%d",&T);
	while (T--){
		scanf("%d%d",&n,&m);fl=0;
		for (i=0;i<m;i++) scanf("%d",&a[i]);
		for (i=0;i<m;i++) scanf("%d",&b[i]);
		n1=a[0];a1=b[0];
		for (i=1;i<m;i++){
			n2=a[i];a2=b[i];
			gcd=ex_gcd(n1,n2,x,y);
			c=a2-a1;
			if (c%gcd){
				fl=1;break;
			}
			x*=c/gcd;
			t=n2/gcd;
			x=(x%t+t)%t;
			a1+=n1*x;
			n1*=n2/gcd;
		}
		if (!a1){//特判 
			a1=1;
			for (i=0;i<m;i++) a1*=a[i]/__gcd(a1,(ll)a[i]);
			n1=a1;
		}
		printf("%lld\n",fl || n<a1?0:(n-a1)/n1+1);
	}
}

pku2142

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
int a,b,c,r,x,y,vx,vy;
int ex_gcd(int a,int b,int &x,int &y){
	if (!b){x=1;y=0;return a;}
	int r=ex_gcd(b,a%b,y,x);
	y-=a/b*x;
	return r;
}
int main(){
	while (~scanf("%d%d%d",&a,&b,&c) && a){
		r=ex_gcd(a,b,x,y);
		a/=r;b/=r;c/=r;
		vx=(x*c%b+b)%b;
		vy=abs((c-a*vx)/b);
		y=(y*c%a+a)%a;
		x=abs((c-b*y)/a);
		if (x+y>vx+vy) x=vx,y=vy;
		printf("%d %d\n",x,y);
	}
}

HDU 4675 GCD of Sequence (2013多校7 1010题数学题)

题意:有n个数,每个数的小于等于M(M <=10^5),现在让你求把原数列改变k个数,使新数列最大公约数为d (d为1~M)的方法数,分别输出
思路:当最大公约数为d时,易得1~M中d的倍数有 M/d个,我们统计原数列中d的倍数的个数cnt,那么所先要将原数列中的非d得倍数的数变成d的倍数,这样的方案数一共有 ( M / d ) n − c n t (M/d)^{n-cnt} (M/d)ncnt 然后还剩下 k − ( n − c n t ) k-(n-cnt) k(ncnt)个数需要变换,那么方案数为 C c n t n − k ∗ ( M / d − 1 ) k − ( n − c n t ) C_{cnt}^{n-k}*(M/d-1)^{k-(n-cnt)} Ccntnk(M/d1)k(ncnt) 那么总的为d的倍数的方案数为 ( M / d ) n − c n t ∗ C c n t n − k ∗ ( M / d − 1 ) k − ( n − c n t ) (M/d)^{n-cnt}*C_{cnt}^{n-k}*(M/d-1)^{k-(n-cnt)} (M/d)ncntCcntnk(M/d1)k(ncnt)此时,还需要减掉为id的倍数的方案数(因为最终答案要求的是最大公约数为d的方案数,而此时的算的是为d的倍数的方案数)这时候先算好组合数,(因为组合数的第二个数是不变的,复杂度从M降为1)并统计好1~M每个数出现的次数(复杂度从n降为lgm),从m开始计算答案,这样复杂度为mlgm。

//https://blog.csdn.net/mowayao/article/details/38440655
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=300002,M=1e9+7;
int n,tmp,k,i,sum,t,d,m,j;
ll C[N],ans[N],cnt[N],x,y;
inline char gc(){
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
#define gc getchar
inline int read(){
    int x=0,fl=1;char ch=gc();
    for (;ch<48||ch>57;ch=gc())if(ch=='-')fl=-1;
    for (;48<=ch&&ch<=57;ch=gc())x=(x<<3)+(x<<1)+(ch^48);
    return x*fl;
}
inline void wri(int a){if(a<0)a=-a,putchar('-');if(a>=10)wri(a/10);putchar(a%10|48);}
void ex_gcd(ll a,ll b,ll &x,ll &y){
	if (!b) x=1,y=0;
	else ex_gcd(b,a%b,y,x),y-=a/b*x;
}
ll inv(ll t){
	ex_gcd(t,M,x,y);
	return (x%M+M)%M;
}
ll pm(ll x,ll y){
	ll z=1;
	for (;y;y>>=1,x=x*x%M)
		if (y&1) z=z*x%M;
	return z;
}
int main(){
	while (~scanf("%d",&n)){
		m=read();k=read();
		tmp=n-k;
		C[tmp]=1;
		memset(cnt,0,sizeof(cnt));
		for (i=tmp+1;i<=n;i++) C[i]=C[i-1]*i%M*inv(i-tmp)%M;
		for (i=0;i<n;i++) x=read(),cnt[x]++;
		for (i=m;i;i--){
			sum=cnt[i];t=0;
			for (j=i+i;j<=m;j+=i) sum+=cnt[j],t=(t+ans[j])%M;
			if (sum<tmp) ans[i]=0;
			else{
				d=m/i;
				ans[i]=(pm(d,n-sum)*C[sum]%M*pm(d-1,sum-tmp)%M-t+M)%M;
			}
		}
		for (i=1;i<=m;i++) wri(ans[i]),putchar(i==m?'\n':' ');
	}
}

HDU 4655 Cut Pieces(2013多校6 1001题简单数学题)

/*https://blog.csdn.net/solotzg/article/details/25082233
if a[i-1] < a[i] then dp[i] = (dp[i-1]*a[i]) + a[0]*a[1]*....a[i-1]*(a[i] - 1);
else 				  dp[i] = (dp[i-1]*a[i]) + a[0]*a[1]*....a[i-2]*(a[i-1]-1)*a[i];
可以手模理解一下 
*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int M=1e9+7,N=1e6+2;
int b[N],T,i,j,n;
ll a[N],dp[N],s1,s2;
int main(){
	scanf("%d",&T);
	while (T--){
		scanf("%d",&n);
		for (i=0;i<n;i++) scanf("%d",&b[i]);
		sort(b,b+n);
		for (i=0,j=0;j<n;i++,j+=2) a[j]=b[i];
		for (i=n-1,j=1;j<n;i--,j+=2) a[j]=b[i];
		dp[0]=a[0];s1=a[0];s2=1;
		for (i=1;i<n;i++){
			if (a[i-1]<a[i]) dp[i]=(dp[i-1]*a[i]%M+s1*(a[i]-1)%M)%M;
			else dp[i]=(dp[i-1]*a[i]%M+s2*(a[i-1]-1)%M*a[i]%M)%M;
			s2=s1;
			s1=s1*a[i]%M;
		}
		printf("%d\n",dp[n-1]);
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值