简单数论专场

A - The Super Powers

UVA - 11752

题解:每个符合的结果的幂都不是素数 所以枚举每个数的非素数幂,注意ull 它输出格式为%lu

#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include<string.h>
#include<set>
#include<algorithm>

#define maxn 100

using namespace std;
bool isPrime[maxn];

void getPrime()
{
	memset(isPrime,true,sizeof(isPrime));
    isPrime[0]=isPrime[1]=false;
    
    for(int i=2;i<maxn;i++)
        if(isPrime[i])
        {
            for(int j=i+i;j<maxn;j+=i)
                isPrime[j] = false;
        }
}
set<unsigned long long> s;

int main()
{
    getPrime();

    s.clear();
    s.insert(1);
    for(int i = 2; i < 65536; i ++ )//2^16
    {
        double m=(64.0 * log(2))/log(i)-1;// ln(x^k)<ln(2^64)-1;//
        unsigned long long tmp = i;

        for(int j=2; j <= ceil(m); j++)
        {
            tmp *= i;
            if(isPrime[j])  continue;
            s.insert(tmp);
        }
    }

    set<unsigned long long> :: iterator it;
    for(it=s.begin();it != s.end(); it ++)
        printf("%lu\n",*it);//
    return 0;
}

B - Maximum GCD

UVA - 11827

//求n个数的最大公约数,处理下输入

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
#include<set>
using namespace std;
#define ll long long
const int maxn=10000010;

int gcd(int a,int b)
{
	return b?gcd(b,a%b):a;
}
char s[maxn];
int a[220];
int main()
{
    int n;
    scanf("%d",&n);getchar();
    while(n--){
        gets(s);
        int len=strlen(s);
        int u=0;
        for(int i=0;i<len;i++){
            int sum=0;
            while(i<len&&s[i]!=' '){
                sum=sum*10+s[i]-'0';
                i++;
            }
            a[u++]=sum;
        }
        int ans=0;
        for(int i=0;i<u;i++)
            for(int j=i+1;j<u;j++)
                ans=max(ans,gcd(a[i],a[j]));
        printf("%d\n",ans);
    }
    return 0;
}

C - Paint Chain

HDU - 3980

题解转载自:https://blog.csdn.net/zhjchengfeng5/article/details/8214768
题意

两个人在一个由 n 个玻璃珠组成的一个圆环上玩涂色游戏,游戏的规则是:
    1、每人一轮,每轮选择一个长度为 m 的连续的、没有涂过色的玻璃珠串涂色
    2、不能涂色的那个人输掉游戏

可以肯定的是,第一个人涂色之后就把环变成了一个长度为 n-m 的链了,那么我们就可以这样划分阶段了:每轮从一些线段中选择一个,并且把那条线段分成 x, m, len-x-m 的三个部分,其中 len 表示线段原来的长度,m 表示的是已经涂色了,那么这个长为 len 的线段能够得到的子状态最多有 len-m+1 个(其实由对称性可知实际的状态数只是这里的一半),变成了两个长度为 x 和 len-x-m 子游戏,由 SG 定理,SG(len)=SG(x)^SG(len-x-m) 而再由 SG 函数的定义式 SG[u]=mex(seg[v]) 其中,状态 u 可以直接得到状态 v,再加上一个记忆化的小优化,AC了

#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
 
using namespace std;
 
int t, n, m;
int f[1005];
bool emerge[1000];
 
int get_sg(int len)
{
    if(len<m) return f[len]=0;
    if(f[len]!=-1) return f[len];
    bool vs[1001]={0};
    for(int i=0; len-i-m>=0; i++)
        vs[get_sg(i)^get_sg(len-i-m)]=1;
    for(int i=0; i<1001; i++)
        if(!vs[i]) return f[len]=i;
}
 
int main()
{
    scanf("%d", &t);
    for(int ca=1; ca<=t; ca++)
    {
        scanf("%d%d", &n, &m);
        memset(f, -1, sizeof(f));
        printf("Case #%d: ", ca);
        if(n<m || get_sg(n-m)) printf("abcdxyzk\n");
        else printf("aekdycoin\n");
    }
    return 0;
}

D - Fliping game

HDU - 4642
题解转载自:https://blog.csdn.net/scnu_jiechao/article/details/9706963
题意:Alice和Bob玩游戏,一个N * M的矩阵,里面是1或0,每人每次选择一个1的位置,然后将这个位置到右下角的整个矩形元素全部取反(1变0,0变1),最后不反操作(没有1)的人输,Alice先行(1 <= N, M <= 100),输出胜者。
因为胜者最后一步一定是将所有的格子变成0,假设最后一个元素是1,每一次翻转,Alice都会将最后一个元素变成0,而Bob每一次都会将最后一个元素变成1,最后也就会是Alice胜;假设最后一个元素是0,每一次翻转,Alice都会将最后一个元素变成1,而Bob每一次都会将最后一个元素变成0,最后也就会是Bob胜。

所以,Alice的输赢取决于最后一个元素,是1就赢,是0就输

#include <cstdio>
 
using namespace std;
 
int main()
{
    int T, N, M, a, i, j;
    scanf("%d", &T);
    while(T--){
        scanf("%d%d", &N, &M);
        for(i = 0; i < N; i++)
            for(j = 0; j < M; j++)
                scanf("%d", &a);
        if(a == 1) printf("Alice\n");
        else printf("Bob\n");
    }
    return 0;
}

E - A Dangerous Maze

LightOJ - 1027
题解转载自:https://blog.csdn.net/yeyeyeguoguo/article/details/46417489
题意:
你在一个迷宫里,面前有n扇们,每个门有一个数字k;
如果k为正数,则通过这扇门,走k分钟就能出去,如果为负数,则通过这扇门走-k的分钟回到迷宫;
走每扇门概率一样.问走出迷宫所需时间的期望值;
思路:首先如果全是负数肯定是inf;然后我们假设我们走出去的期望时间是d;
那么拿第三个样例举例子; d = 1/3 * 3 + 1/3( 6 + d) + 1/3 (9 + d);
意思就是每扇门被选择的概率是1/3;选选第一扇门要花3分钟出去,选第二扇门要6 + d(花6分钟返回原地,在花期望d出去);然后根据这个式子求出d;并用分数表示;

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

struct frac{
	int u;
	int d;
}f;

frac add(frac a, frac b){
	if(a.d == 0)
		return b;
	frac tmp;
	int up = a.u * b.d + a.d * b.u;
	int down = a.d * b.d;
	int c = __gcd(up, down);//系统自带的 gcd 
	tmp.u = up / c;
	tmp.d = down / c;
	return tmp;
}

int main() {
	int t, n;
	int cas = 1;
	scanf("%d",&t);
	while(t--) {
		scanf("%d",&n);
		int d = 0;
		frac num;
		num.u = 0;
		num.d = 0;
		int tmp;
		for(int i = 0; i < n; i++) {
			scanf("%d",&tmp);
			if(tmp > 0) {
				f.u = tmp;
				f.d = n;
				num = add(num, f);
			}else {
				f.u = -tmp;
				f.d = n;
				num = add(num, f);
				d++;
			}
		}
		if(d == n) {
			printf("Case %d: inf\n",cas++);
			continue;
		}
		num.u *= n;
		num.d *= (n - d);
		int c = __gcd(num.u, num.d);
		printf("Case %d: %d/%d\n",cas++, num.u / c, num.d / c);
	}
	return 0;
}	

F - Birthday Paradox

LightOJ - 1104
题解转载自:https://blog.csdn.net/hyczms/article/details/46460401
题意:假设一年有n天,问至少有多少个人,能保证至少其中两个人的生日在同一天的概率大于等于0.5。
题解:要计算至少两个人的生日同天概率可以逆着算所有人不同天生日的概率小于0.5,那么人数就是x = 1 * (n - 1)/n * (n-2)/n * … 直到x是小于0.5的

#include <stdio.h>
#include <string.h>
#include <math.h>
int n;

int main() {
    int t, cas = 1;
    scanf("%d", &t);
    while (t--) {
        scanf("%d", &n);
        int cnt = 0;
        double temp = 1;
        while (temp > 0.5) {
        	cnt++;
            temp *= (n - cnt) * 1.0 / n;
        }
        printf("Case %d: %d\n", cas++, cnt);
    }
    return 0;
}

G - Dice (III)

LightOJ - 1248
题解转载自:https://blog.csdn.net/chy20142109/article/details/51774631
题意:有一个n面的骰子,每次投掷每个面都是等概率出现,求所有面都出现的期望投掷次数。思路:f[i]表示已经出现了i个面,还需要投掷的期望次数,f[n] = 0 , f[i] = i/n * f[i] + ( n - i ) / n * f[i+1] + 1 ,
化简后f[i] = f[i+1] + n / ( n - i ) , 所以答案就是∑n/i 1<=i<=n。

#include<cstdio>
#include<cmath>
using namespace std;
int main()
{
	int T,n,t=1;
	scanf("%d",&T);
	while(T--){
		scanf("%d",&n);
		double ans=0.0;
		for(int i=1;i<=n;i++)
			ans+=1.0*n/i;
		printf("Case %d: %f\n",t++,ans);
	}
	return 0;
}

H - Finite or not?

CodeForces - 984C
题解转载自:
题意:输入p q b问p/q在 b进制中是否为有限小数
题解:先gcd去除p的贡献,然后对于1/q是否能被b表示,则看1/q=1/b+1/b^2+…+能否被表示,对1/q每次都乘以b,再约分,(这个过程相当于q和无穷多个b进行疯狂约分),如果最后1/q能化为1,则说明1/q在b进制为有限小数。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
#include<set>
using namespace std;
#define ll long long
const int maxn=300010;

ll p,q,b;
ll gcd(ll a,ll b)
{
	return b?gcd(b,a%b):a;
}
//int gcd(int a,int b)
//{
//	return b?gcd(b,a%b):a;
//}
bool ok()
{
	ll m=gcd(p,q);
	q/=m;
	
	m=b;
	while(q!=1){
		m=gcd(q,m);
		q/=m;
		if(m==1) break;
	}
	
	if(q==1)
		return true;
	return false;
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--){
		scanf("%I64d%I64d%I64d",&p,&q,&b);
		if(!p||ok())
			printf("Finite\n");
		else
			printf("Infinite\n");
	}
    return 0;
}


I - Modular Equations

CodeForces - 495B
题意:满足 a % x = = b a\%x==b a%x==b的所有x,输入a b输出满足的x的个数,有无穷个输出无穷
题解:a%x==b <=> (a-b)%x==0

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
#include<set>
using namespace std;
#define ll long long
const int maxn=10000010;
set<int> st;
int get(int x,int b)
{
	st.clear();
	int ans=0,m=sqrt(x);
	for(int i=1;i<=m;i++){
		if(x%i==0){
			int j=x/i;
			if(i>b&&st.find(i)==st.end()){
				ans++;
				st.insert(i);
				//printf("i:%d\n",i);
			}
			if(j>b&&st.find(j)==st.end()){
				//printf("j:%d\n",j);
				st.insert(j);
				ans++;
			}
		}
	}
	//if(x%m==0) ans--;
	return ans;
}
int main()
{
	int a,b;
	while(~scanf("%d%d",&a,&b)){
		if(a==b){
			printf("infinity\n");
			continue;
		}
		if(b>a){
			printf("0\n");
			continue;
		}
		printf("%d\n",get(a-b,b));
	}
	return 0;
}
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
#include<set>
using namespace std;
#define ll long long
const int maxn=10000010;
set<int> st;
int get(int x,int b)
{
	st.clear();
	int ans=0,m=sqrt(x);
	for(int i=1;i<=m;i++){
		if(x%i==0){
			int j=x/i;
			if(i>b&&st.find(i)==st.end()){
				ans++;
				st.insert(i);
				//printf("i:%d\n",i);
			}
			if(j>b&&st.find(j)==st.end()){
				//printf("j:%d\n",j);
				st.insert(j);
				ans++;
			}
		}
	}
	//if(x%m==0) ans--;
	return ans;
}
int main()
{
	int a,b;
	while(~scanf("%d%d",&a,&b)){
		if(a==b){
			printf("infinity\n");
			continue;
		}
		if(b>a){
			printf("0\n");
			continue;
		}
		printf("%d\n",get(a-b,b));
	}
	return 0;
}

J - Concatenated Multiples

CodeForces - 1029D

题解转载自:http://crazyforsaken.com/?p=742
题意 对于两个数字a和b来说,如果把他们连起来取模k为0就是答案的一个贡献,现在给你n个数问有多少对(xy和yx是两种不同的)对答案有贡献?思路 对于x和y来说,如果x在前面的话,需要考虑y的位数p,对于题意显然有 ( x ∗ 1 0 p + y ) % k = = 0 (x*10^p+y)\%k==0 (x10p+y)%k==0。作出相应的变形就是
( x ∗ 1 0 p ) % k = = ( k − y % k ) % k (x*10^p)\%k==(k-y\%k)\%k (x10p)%k==(ky%k)%k那么我们对于所有的输入的t,都可以处理一下把它当作前面那个数字,用mp[i][x]表示后面的数为i位时,x=t*10^i%k有这样的答案出现过,然后再遍历所有的数字当成后面的数,根据其位数去找mp[l][(k-y%k)%k]是否有对应的数存在,最后去重即可。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
#include<set>
#include<map>
using namespace std;
#define ll long long
const int maxn=200010;

int n,k;
int a[maxn];

map<int,ll> mp[15];
int getlen(int x)
{
	int ans=0;
	while(x){
		x/=10;
		ans++;
	}
	if(!ans) ans++;
	return ans;
}
int main()
{
	while(~scanf("%d%d",&n,&k)){
		for(int i=1;i<=n;i++)
			scanf("%d",&a[i]);
		//memset(mp,0,sizeof(mp));
		for(int i=0;i<15;i++)
			mp[i].clear();
		for(int i=1;i<=n;i++){
			ll p=1LL;
			for(int j=1;j<=10;j++){
				p=p*10LL%k;
				mp[j][a[i]%k*p%k]++;
			}
		}
		ll ans=0;
		for(int i=1;i<=n;i++){
			ll p=1LL;
			int l=getlen(a[i]);
			//printf("%d: len:%d\n",i,l);
			for(int j=1;j<=l;j++){
				p=p*10LL%k;
			}
			ans+=1LL*mp[l][(k-a[i]%k)%k];
			if((k-a[i]%k)%k==a[i]%k*p%k)
				ans--;
		}
		printf("%lld\n",ans);
	}
}

K - Diagonal Walking v.2

CodeForces - 1036B
题意:给一个点(n,m) 走k步,问从(0,0)出发走k步到达(n,m)时,能最多走多少对角线,如果走不到输出-1
题意:从出发点到终点,先取x,y中最大的m最小的mn,先走到同一线上,在贪心的上下走,对剩下到达终点后的步数,也贪心的上下走,注意分奇数、偶数的情况,终点和出发点一样的情况。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
#include<set>
using namespace std;
#define ll long long
const int maxn=10000010;

int n;
int main()
{
	int t;
    scanf("%d",&t);
    while(t--){
    	ll x,y,k;
        scanf("%lld%lld%lld",&x,&y,&k);
        ll mn=min(x,y),mx=max(x,y);
        if(mx>k){
        	printf("-1\n");
        	continue;
		}
		ll ans=(mx-mn)/2*2+mn;
		if((k-mx)%2){
			k--;
			if((mx-mn)%2){
				ans++;//printf("SD\n");
			}else if(ans){
				ans--;
			}else{
				printf("-1\n");
				continue;//
			}
		}
		ans+=k-mx;
		printf("%lld\n",ans);
    }
    return 0;
}
/*
99
2 3 3

*/

L - Vasya and Arrays

CodeForces - 1036D
题意:有两个长度为n和m的序列A和B,每次操作可以将序列连续的几个数合并为1个,该数的值是那连续几个数的和。现在进行若干次操作让A和B相等,问操作形成的相等序列的最大长度是多少。
题解:从左向右扫,并记录A和B序列的和sum1、sum2,每当和相等时,结果+1,sum1与sum2清0

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
#include<set>
using namespace std;
#define ll long long
const int maxn=300010;

int a[maxn],b[maxn];
int n,m;
int main()
{
	while(~scanf("%d",&n)){
		ll cur1=0,cur2=0;//
		for(int i=1;i<=n;i++){
			scanf("%d",&a[i]);
			cur1+=1LL*a[i];
		}
		scanf("%d",&m);
		for(int i=1;i<=m;i++){
			scanf("%d",&b[i]);
			cur2+=1LL*b[i];
		}
		if(cur1!=cur2){
			printf("-1\n");
			continue;
		}
		int i=1,j=1;
		cur1=a[1],cur2=b[1];
		int len=0;
		while(i<=n&&j<=m){
			if(cur1==cur2){
				if(cur1){
					cur1=cur2=0;
					len++;
				}else{
					cur1+=1LL*a[++i];
					cur2+=1LL*b[++j];
				}
			}
			else if(cur1<cur2){
				cur1+=1LL*a[++i];
			}
			else{
				cur2+=1LL*b[++j];
			}
		}
		printf("%d\n",len);
	}
    return 0;
}


M - Vasya’s Function

CodeForces - 837E
题解转载自:https://blog.csdn.net/calabash_boy/article/details/76652792
题意:定义F(a,0) = 0,F(a,b) = 1 + F(a,b - GCD(a,b)。给定 x 和 y (<=1e12)求F(x,y)。 题解:a=AGCD(a,b) b=BGCD(a,b),那么b-GCD(a,b) = (B-1)GCD(a,b),如果此时A和B-1依然互质,那么GCD不变下一次还是要执行b-GCD(a,b)。那么GCD什么时候才会变化呢?就是说找到一个最小的S,使得(B-S)%T=0其中T是a的任意一个因子。变形得到:B%T=S于是我们知道S=min(B%T)。也就是说b剪掉了S次相同的一个GCD之后,ab有了新的GCD。新的GCD等于原来的GCDT,可以把a、b都/T,同时GCD*T,这样问题化归为上述同样的问题,进行迭代。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int main() {
	LL x, y;
	cin >> x >> y;
	LL g = __gcd(x, y);
	x /= g, y /= g;
	vector<LL> a;
	for (LL i = 2; i * i <= x; ++ i) {
		while (x % i == 0) {
			x /= i;
			a.push_back(i);
		}
	}
	if (x > 1) a.push_back(x);
	LL ans = 0;
	while (y) {
		LL g = y;
		for (LL i : a) {
			g = min(g, y % i);
		}
		ans += g;
		y -= g;
		vector<LL> b;
		for (LL i : a) {
			if (y % i == 0) {
				y /= i;
			}
			else {
				b.push_back(i);
			}
		}
		a.swap(b);
	}
	cout << ans << endl;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
4S店客户管理小程序-毕业设计,基于微信小程序+SSM+MySql开发,源码+数据库+论文答辩+毕业论文+视频演示 社会的发展和科学技术的进步,互联网技术越来越受欢迎。手机也逐渐受到广大人民群众的喜爱,也逐渐进入了每个用户的使用。手机具有便利性,速度快,效率高,成本低等优点。 因此,构建符合自己要求的操作系统是非常有意义的。 本文从管理员、用户的功能要求出发,4S店客户管理系统中的功能模块主要是实现管理员服务端;首页、个人中心、用户管理、门店管理、车展管理、汽车品牌管理、新闻头条管理、预约试驾管理、我的收藏管理、系统管理,用户客户端:首页、车展、新闻头条、我的。门店客户端:首页、车展、新闻头条、我的经过认真细致的研究,精心准备和规划,最后测试成功,系统可以正常使用。分析功能调整与4S店客户管理系统实现的实际需求相结合,讨论了微信开发者技术与后台结合java语言和MySQL数据库开发4S店客户管理系统的使用。 关键字:4S店客户管理系统小程序 微信开发者 Java技术 MySQL数据库 软件的功能: 1、开发实现4S店客户管理系统的整个系统程序; 2、管理员服务端;首页、个人中心、用户管理、门店管理、车展管理、汽车品牌管理、新闻头条管理、预约试驾管理、我的收藏管理、系统管理等。 3、用户客户端:首页、车展、新闻头条、我的 4、门店客户端:首页、车展、新闻头条、我的等相应操作; 5、基础数据管理:实现系统基本信息的添加、修改及删除等操作,并且根据需求进行交流信息的查看及回复相应操作。
现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本微信小程序医院挂号预约系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息,使用这种软件工具可以帮助管理人员提高事务处理效率,达到事半功倍的效果。此微信小程序医院挂号预约系统利用当下成熟完善的SSM框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的MySQL数据库进行程序开发。微信小程序医院挂号预约系统有管理员,用户两个角色。管理员功能有个人中心,用户管理,医生信息管理,医院信息管理,科室信息管理,预约信息管理,预约取消管理,留言板,系统管理。微信小程序用户可以注册登录,查看医院信息,查看医生信息,查看公告资讯,在科室信息里面进行预约,也可以取消预约。微信小程序医院挂号预约系统的开发根据操作人员需要设计的界面简洁美观,在功能模块布局上跟同类型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问题提供了一些实用的解决方案。可以说该程序在帮助管理者高效率地处理工作事务的同时,也实现了数据信息的整体化,规范化与自动化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值