codeforces数论专题总结

codeforces数论专题总结(1300~1800)

1444A Division (1500)

题意:输入两个数p,q. 求最大的数x,满足以下条件:

  • p%x==0
  • x%q!=0

一共两种情况:

  1. p%q!=0 答案就是p
  2. p%q==0,那么对q进行质因子分解得:p = $ p_{1}^{a1} p_{2} ^ {a2}…* p_{n} ^{an} $ 因为x和q都是p得因子,那么x质因子分解以后和q的分解一定不相同,要么质因子个数不同,要么某个质因子的数量不同;所以枚举q的每个质因子的个数,让q不断的去除以某个质因子,直到得到满足条件的x,所有情况取最大值;
#include <bits/stdc++.h>
using namespace std;
#define sf(a) scanf("%d",&a)
#define sff(a,b) scanf("%d %d",&a,&b)
#define sfff(a,b,c) scanf("%d %d %d",&a,&b,&c)
#define pf(a) printf("%d\n",a)
#define pff(a,b) printf("%d %d\n",a,b)
#define PII pair<pair<int,int>,int> 
typedef long long ll;
const int N=5e4+7,INF=0x3f3f3f3f;
vector<int> v;
int main()
{
	int t;sf(t);
	while(t--)
	{
		ll a,b;
		cin >>a>>b;
		v.clear();
		if(a>=b)
		{
			if(a%b!=0) cout <<a<<endl;
			else
			{
				ll ans=0,x=b;
				for(int i=2;i*i<=b;i++)
				{
					if(b%i==0)
					{
						while(b%i==0) b/=i;
						v.push_back(i);
					}
				}
				if(b>1) v.push_back(b);
				for(int i=0;i<v.size();i++)
				{
					int j=v[i];
					ll temp=a;
					while(temp%j==0)
					{
						temp/=j;
						if(temp%x!=0&&a%temp==0)
						{
							ans=max(ans,temp);
							break;
						}
					}
				}
				cout <<ans<<endl;
			}
		}
		else cout <<a<<endl;
	}
	
}

1462D Add to Neighbour and Remove(1400)

题意:给出一个数组,每次可以合并任意两个数,问至少多少次合并操作后可以使数组中的数全都相同;
思路:因为每次只能合并相邻的,所以合并是一段一段的;假设合并后数组长度为x,那么数组中的每个数都是sum/x,所以每一段合并后的和都应该是sum/x;枚举数组合并后的长度(1~n)取最大值(如果从n往1枚举,那么第一次得出的结果就是最优解)

#include <bits/stdc++.h>
using namespace std;
#define sf(a) scanf("%lld",&a)
#define sff(a,b) scanf("%d %d",&a,&b)
#define sfff(a,b,c) scanf("%d %d %d",&a,&b,&c)
#define pf(a) printf("%d\n",a)
#define pff(a,b) printf("%d %d\n",a,b)
#define PII pair<pair<int,int>,int> 
typedef long long ll;
const int N=1e6,INF=0x3f3f3f3f;
ll a[N],sum;
int main()
{
	int t;cin >>t;
	while(t--)
	{
		int n;cin >>n;sum=0;
		for(int i=1;i<=n;i++)
		{
			cin >>a[i];sum+=a[i];
		}
		ll ans=n;
		for(int i=n;i>=1;i--)
		{
			if(sum%i==0)
			{
				ll res=sum/i,x=0,y=0;
//				cout <<"%%"<<res<<endl;
				for(int j=1;j<=n;j++)
				{
					if(y==-1) break; 
					x+=a[j];
//					cout <<x<<endl;
					if(x==res) y=1,x=0;
					else if(x>res) y=-1;
				}
				if(x<res&&x!=0) y=-1;
				if(y>0) 
				{
					ans=n-i;
					break;
				}
			}
			
		}
		cout <<ans<<endl;
	}
}

1423K Lonely Numbers(1600)

题意:当一个数满足下面条件时是孤独的:没有任何一个数和他满足下列关系:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tXScN9PJ-1608465174526)(./1608212464790.png)]就是不能组成三角形,则这个数是孤独的;问1-n有多少个数是孤独的
思路:分奇偶讨论:

  • 偶数:假设两个相邻的偶数x,y;他们的gcd一定是2,又因为x/gcd(x,y) , y/gcd(x,y)之间相差1,所以三者肯定能构成三角形
  • 奇数:奇数分两种情况:合数,质数;对于合奇数一定符合情况,对于质数,假设质数为x,那么只有另一个数大于等于 x 2 x^2 x2 时才满足条件,所以只需要找出来 n ↔ n \sqrt{n}\leftrightarrow n n n之间的质数即可
#include <bits/stdc++.h>
using namespace std;
#define sf(a) scanf("%d",&a)
#define sff(a,b) scanf("%d %d",&a,&b)
#define sfff(a,b,c) scanf("%d %d %d",&a,&b,&c)
#define pf(a) printf("%d\n",a)
#define pff(a,b) printf("%d %d\n",a,b)
const int N=2e6+7;
int primes[N], cnt;
bool st[N]; 
 
void get_primes(int n)
{
    for (int i = 2; i <= n; i ++ )
    {
        if (!st[i]) primes[cnt ++ ] = i;
        for (int j = 0; primes[j] <= n / i; j ++ )
        {
            st[primes[j] * i] = true;
            if (i % primes[j] == 0) break;
        }
    }
}
int main()
{
	//ios::sync_with_stdio(false);
	get_primes(1e6);
	int t;sf(t);
	while(t--)
	{
		int n;sf(n);
		if(n==1)
		{
			puts("1");
			continue;
		}
		int ans=1;
		int res=sqrt(n);
		int l=upper_bound(primes,primes+cnt,res)-primes;
		int r=upper_bound(primes,primes+cnt,n)-primes;
		if(l==0&&primes[0]>res) ans+=r-l;
		else l--,ans+=(r-l-1);
		pf(ans);
	}
}

1407B Big Vova(1300)

题意:给出一个数组a,要求用数组中所有的数字构造出一个数组b,然后数组c的定义是[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yBZLCcND-1608465174529)(./1608367631741.png)]
要求构造数组b,使得c数组最大
思路:暴力,每次遍历当前没用过的数,找到使得gcd最大的数字并且保存和标记

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e3+2;
int a[N],b[N],st[N];
bool cmp(int x,int y) 
{
	return x>y;
}
int main()
{
	int t;
	cin >>t;
	while(t--)
	{
		memset(st,0,sizeof st);
		int n;
		cin >>n;
		for(int i=0;i<n;i++) cin >>a[i];
		sort(a,a+n,cmp);
		int x,y,cnt=0;
		int gcd=a[0];
		//cout <<gcd<<endl;
		b[cnt++]=a[0];
		st[0]=1;
		while(cnt<n)
		{
			int temp=-1;
			for(int j=0;j<n;j++)
			{
				if(st[j]) continue;
				int res=__gcd(gcd,a[j]);
				//cout <<res<<" ##"<<endl;
				if(res>temp) y=j,temp=res;
			}
//			cout <<temp<<endl;
//			cout <<"y"<<" "<<y<<endl;
			b[cnt++]=a[y];
			st[y]=1;
			gcd=__gcd(gcd,a[y]);
		}
		for(int i=0;i<cnt;i++) cout <<b[i]<<" ";
		cout <<endl;
	}
}

1409C Yet Another Array Restoration(1200)

断更…(不完美的退役)

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值