数论

  • HDU5974  gcd

Given two positive integers a and b,find suitable X and Y to meet the conditions:
                                                        X+Y=a
                                              Least Common Multiple (X, Y) =b

给出a,b,求满足题意的x,y。

设X,Y的最大公约数为t,即gcd(X,Y)=t,那么有X=k1t,Y=k2t,其中k1,k2互质,X+Y=(k1+k2)t,lcm(X,Y)=XYt=k1k2t,又因为k1+k2与k1k2互质,所以gcd(X+Y,lcm(X,Y))=t,又有gcd(X,Y)=t,所以gcd(X,Y)=gcd(X+Y,lcm(X,Y))=gcd(a,b)=t
然后又lcm(X,Y)=XYt,Y=a−X。 求出x,y的最大公约数。掌握互质!

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
int gcd(int x,int y)
{
	return y==0?x:gcd(y,x%y);
}
int main()
{
	int a,b,x,y,n,t,da;
	while(scanf("%d%d",&a,&b)!=EOF)
	{
		t=gcd(a,b);da=a*a-4*t*b;
		if(da<0||sqrt(da)!=(int)sqrt(da)||(a+(int)sqrt(da))%(2*t)!=0)  printf("No Solution\n");
		else{
			n=(a+(int)sqrt(da))/(2*t);
			x=n*t;y=a-x;
			if(x>y)  swap(x,y);
			printf("%d %d\n",x,y);
		}
	}
	return 0;
}
  •  a,c的最大公约数是b,b不等于c,给出a,b,求c。

简单题,以为直接b乘以2,必须判断最大公约数是否为b。。。c+=b。。。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
int gcd(int m,int n)
{
	return n==0?m:gcd(n,m%n);
}
int main()
{
	int n,a,b,c;
	scanf("%d",&n);
	while(n--)
	{
		scanf("%d%d",&a,&b);
		c=b*2;
		while(1)
		{
			if(gcd(a,c)==b)    break;
			else    c+=b;
		}
		printf("%d\n",c);
	}
	return 0;
 } 

 

  • 欧拉函数

In this problem, given integer k , your task is to find the k -th smallest positive integer n , that φ(n) is a composite number. 

 写出欧拉函数,再判断是否是合数后,发现只有1时是5,其余每个加5都是合数。

写出欧拉函数,枚举每个数的欧拉函数值,判断是否为合数,找规律。


int main()
{
	int n;
	long long x;
	scanf("%d",&n);
	while(n--)
	{
		scanf("%lld",&x);
		if(x==1)  printf("5\n");
		else  printf("%lld\n",x+5);
	}
	return 0;
 } 
  •  HDU5978 begin or not to begin

很好理解,n是黑球个数,为偶数时,加一个红球,总数为奇数,先抽的人多一次机会,赢的几率大

                                        n为奇数时,加一个红球,总数为偶数,几率一样大。

 

  • 素数 给一个数,求它之前相差为2的素数有几对

Twin Prime Conjecture states that "There are infinite consecutive primes differing by 2".Now given any positive integer N (< 10^5), you are supposed to count the number of twin primes which are no greater than N.

因为是统计出现次数,不用记录那些数,数组记录次数就行,直接读取。循环中j一次变化2,写为j+=2!!!

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
int a[100005];
bool prime(int k)
{
	for(int i=2;i*i<=k;i++)
	{
		if(k%i==0)  return false;
	}
	return true;
}
void fun()
{
	int count=0;
	for(int j=5;j<100002;j+=2)
	{
		if(prime(j-2)&&prime(j)){
			count++;
		}
		a[j]=count;
	}
}
int main()
{
	int n,count;
	memset(a,0,sizeof(a));
	fun();
	while(scanf("%d",&n)!=EOF&&n>0)
	{
		if(n==0||n==1||n==2){
			printf("0\n");
		}
		else{
			if(n%2==0)   printf("%d\n",a[n-1]);
			else         printf("%d\n",a[n]);
		}
	}
	return 0;
 } 
  • 素数

一个十进制数,如果是“丑陋素数”,而且它的各位数字和也是“丑陋素数”,则称之为“完美素数”,如29,本身是“丑陋素数”,而且2+9 = 11也是“丑陋素数”,所以它是“完美素数”。
  给定一个区间,你能计算出这个区间内有多少个“完美素数”吗?

与上题类似,直接记录出现次数!!!注意端点问题

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
int a[1000000];
bool prime(int k)
{
	for(int i=2;i*i<=k;i++)
	{
		if(k%i==0)  return false; 
	}
	return true;
}
void fun()
{
	int sum,x,g,count=0;
	for(int i=2;i<=1000000;i++)
	{
		if(prime(i))
		{
			sum=0;x=i;
			while(x>=1)
			{
				g=x%10;
				sum+=g;
				x/=10;
			}
			if(prime(sum))    count++;
		}
		a[i]=count;
	}
}
int main()
{
	int t,j=0,l,r;
	scanf("%d",&t);
	memset(a,0,sizeof(a));
	fun();
	while(t--)
	{
		j++;
		scanf("%d%d",&l,&r);
		//printf("%d %d\n",a[l-1],a[r]);
		printf("Case #%d: %d\n",j,a[r]-a[l-1]);
	}
	return 0;
}
  • 欧拉函数

 

通式:

其中p1, p2……pn为x的所有质因数,x是不为0的整数。注意:每种质因数只一个。 比如12=2*2*3那么φ(12)=12*(1-1/2)*(1-1/3)=4

 

 

int eular(int n)
{
	int ret=1;
	for(int i=2;i*i<=n;i++)
	{
		if(n%i==0) 
		{
			n/=i;ret*=i-1;
			while(n%i==0)
			{
				n/=i;ret*=i;
			}
		}
	}
	if(n>1)  ret*=n-1;
	return ret;
}
  • 机器人走方格 用组合数n+m-2中取n-1

除数求逆元,10的9次加7是质数,a^(p-2)

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const ll mod=1000000007;
ll pow(ll a,ll b)
{
    ll ans=1,base=a;
    while(b!=0)
	{
        if(b&1!=0)    ans=ans*base%mod;
        base=base*base%mod;
        b>>=1;
    }
    return ans;
}
int main()
{
	ll m,n,i,sum=1;
	scanf("%lld%lld",&m,&n);
	for(i=m+n-2;i>n-1;i--)
	{
		sum*=i;
		sum%=mod;
	}
	for(i=2;i<m;i++)
	{
		sum=(sum*pow(i,mod-2))%mod;
	}
	printf("%lld\n",sum);
	return 0;
}
  • 卡特兰数 h(n)=C(n,2*n)/(n+1)

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const ll mod=1000000007;
const int maxn=1000005;
ll a[maxn];
ll pow(ll a,ll b)
{
    ll ans=1,base=a;
    while(b!=0)
	{
        if(b&1!=0)    ans=ans*base%mod;
        base=base*base%mod;
        b>>=1;
    }
    return ans;
}
void fun()
{
	a[0]=0;a[1]=1;ll i=2;
	while(i<=1000000)
	{
	   a[i]=(a[i-1]*(2*i-1))%mod;a[i]=(a[i]*(2*i))%mod;
	   a[i]=(a[i]*pow(i,mod-2))%mod;a[i]=(a[i]*pow(i+1,mod-2))%mod;
	   i++;
    }
}
int main()
{
	ll t,n,i,sum,j=0;
	fun();
	scanf("%lld",&t);
	while(t--)
	{
		j++; sum=1;
		scanf("%lld",&n);
	    printf("Case #%lld:\n",j);
	    printf("%lld\n",a[n]);
	}
	return 0;
}
  • 思维题

(wi-abi)的平方 从i=1到i=n的和,给出wi,bi可取正负1,展开式子得到关于a的二元一次方程,利用-b/(2*a)求出最小值时a取值,带入原式得到式子,要求结果以分数形式输出,计算过程分开计算,最后各自除以它们的最大公约数。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b)
{
	return b==0?a:gcd(b,a%b);
}
int main()
{
	ll t,n,p,q,a,sum1,sum2;
	scanf("%lld",&t);
	while(t--)
	{
		sum1=0;sum2=0;
		scanf("%lld",&n);
		for(ll i=0;i<n;i++)
		{
			scanf("%lld",&a);
			sum1+=abs(a);
			sum2=sum2+a*a;
		}
	    p=sum2*n-sum1*sum1;q=n;
		ll yue=gcd(p,q);
		p=p/yue;q=q/yue;
		printf("%lld/%lld\n",p,q);
	}
	return 0;
}
  • A number sequence is defined as follows:

    f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7.

    Given A, B, and n, you are to calculate the value of f(n).

取模7,所以fn有7*7=49种可能。一定有循环

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
int main()
{
    int a,b,n,f[50];
	while(scanf("%d%d%d",&a,&b,&n)!=EOF&&(a||b||n))
	{
	    f[1]=1;f[2]=1;
		for(int i=3;i<=48;i++)
		{
		   f[i]=(a*f[i-1]+b*f[i-2])%7;
	    }
	    printf("%d\n",f[n%48]);
	} 
    return 0;
 } 
  • tr(a^k)

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int mod=9973;
struct mat
{
	ll a[11][11];
};
mat multi(mat a,mat b,ll n)
{
    mat c;
	memset(c.a,0,sizeof(c.a));
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
           for(int k=0;k<n;k++)
               c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j])%mod;
    return c;
}
mat pow(ll n,ll k,mat d)
{
    mat res;
    memset(res.a,0,sizeof(res.a));
    for(ll i=0;i<n;i++)
    {
    	res.a[i][i]=1;
	}
	while(k)
	{
		if(k&1)  res=multi(res,d,n);
		d=multi(d,d,n);
		k>>=1;
	}
	return res;
}
int main()
{
	ll t,n,k,sum;
	mat d;
	scanf("%lld",&t);
	while(t--)
	{
		sum=0;
		scanf("%lld%lld",&n,&k);
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<n;j++)
			{
				scanf("%lld",&d.a[i][j]);
			}
		}
		mat result=pow(n,k,d);
		for(int i=0;i<n;i++)
		{
			sum=(sum+result.a[i][i])%mod;
		}
		printf("%lld\n",sum);
	}
	return 0;
}
  •  

    Lele now is thinking about a simple function f(x).

    If x < 10 f(x) = x.
    If x >= 10 f(x) = a0 * f(x-1) + a1 * f(x-2) + a2 * f(x-3) + …… + a9 * f(x-10);
    And ai(0<=i<=9) can only be 0 or 1 .

    Now, I will give a0 ~ a9 and two positive integers k and m ,and could you help Lele to caculate f(k)%m.

 

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
ll k,m;
struct mat
{
	ll a[10][10];
};
mat multi(mat a,mat b)
{
    mat c;
	memset(c.a,0,sizeof(c.a));
    for(int i=0;i<10;i++)
        for(int j=0;j<10;j++)
           for(int k=0;k<10;k++)
               c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j])%m;
    return c;
}
ll pow(ll k,mat d,mat f)
{
    mat res;
    memset(res.a,0,sizeof(res.a));
    for(ll i=0;i<10;i++)
    {
    	res.a[i][i]=1;
	}
	while(k)
	{
		if(k&1)  res=multi(res,d);
		d=multi(d,d);
		k>>=1;
	}
	res=multi(res,f);
	return res.a[0][0];
}
int main()
{
	mat d,f;
	memset(f.a,0,sizeof(f.a));
	for(int j=0;j<10;j++)
	{
		f.a[j][0]=9-j;
	}
	while(scanf("%lld%lld",&k,&m)!=EOF)
	{
		if(k<10)
		{
			printf("%lld\n",k%m);continue;
		}
		memset(d.a,0,sizeof(d.a));
		for(int i=0;i<10;i++)
		{
			scanf("%lld",&d.a[0][i]);
			if(i<9)    d.a[i+1][i]=1;
		}
		printf("%lld\n",pow(k-9,d,f));
	}
	return 0;
}

 

  • In our daily life we often use 233 to express our feelings. Actually, we may say 2333, 23333, or 233333 ... in the same meaning. And here is the question: Suppose we have a matrix called 233 matrix. In the first line, it would be 233, 2333, 23333... (it means a 0,1 = 233,a 0,2 = 2333,a 0,3 = 23333...) Besides, in 233 matrix, we got a i,j = a i-1,j +a i,j-1( i,j ≠ 0). Now you have known a 1,0,a 2,0,...,a n,0, could you tell me a n,m in the 233 matrix?

  • Input

    There are multiple test cases. Please process till EOF.

    For each case, the first line contains two postive integers n,m(n ≤ 10,m ≤ 10 9). The second line contains n integers, a 1,0,a 2,0,...,a n,0(0 ≤ a i,0 < 2 31).

    Output

    For each case, output a n,m mod 10000007.

给出第一列数,每个数是上方和左方的数相加,求a n,m的值。 m数据大,所以一列一列求,找规律!!!

一定要注意题中所给数据,mod的大小!!!

 


#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const ll mod=10000007;
struct mat
{
	ll a[15][15];
};
mat multi(mat a,mat b,ll n)
{
    mat c;
	memset(c.a,0,sizeof(c.a));
    for(int i=0;i<n+2;i++)
        for(int j=0;j<n+2;j++)
           for(int k=0;k<n+2;k++)
               c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j])%mod;
    return c;
}
ll pow(ll m,ll n,mat d,mat f)
{
    mat res;
    memset(res.a,0,sizeof(res.a));
    for(ll i=0;i<n+2;i++)
    {
    	res.a[i][i]=1;
	}
	while(m)
	{
		if(m&1)  res=multi(res,d,n);
		d=multi(d,d,n);
		m>>=1;
	}
	res=multi(res,f,n);
	return res.a[n][m];
}
int main()
{
	ll n,m; 
	while(scanf("%lld%lld",&n,&m)!=EOF)
	{
	    mat d,f;
    	memset(f.a,0,sizeof(f.a));
		memset(d.a,0,sizeof(d.a));
		f.a[0][0]=23;
		for(int i=0;i<=n+1;i++)
		{
			if(i==0)  
			{
				f.a[i][0]=23;d.a[i][0]=10;
			}
			else if(i==n+1)   f.a[i][0]=3;
			else
			{
				scanf("%lld",&f.a[i][0]);d.a[i][0]=10;
			}
			d.a[i][n+1]=1;      
		}
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=i;j++)
			{
				d.a[i][j]=1;
			}
		}
		printf("%lld\n",pow(m,n,d,f));
	}
	return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值