#2020寒假集训#数论入门(Number Theory)代码笔记

整除

#2020寒假集训#数论入门(Number Theory)代码笔记_第1张图片

同余

#2020寒假集训#数论入门(Number Theory)代码笔记_第2张图片

最大公因数(GCD)

#2020寒假集训#数论入门(Number Theory)代码笔记_第3张图片

欧几里得算法(辗转相除法)

int gcd(int a,int b) {return a==0?b:gcd(b%a,a);}

最小公倍数(LCM)

int gcd(int a,int b) {return a==0?b:gcd(b%a,a);}
int lcm(int a,int b) {return a*b/gcd(a,b);}

贝祖定理

  • 如果a、b是整数,那么一定存在整数x、y使得ax+by=gcd(a,b)
  • 如果ax+by=m有解,那么m一定是gcd(a,b)的若干倍(可以来判断一个这样的式子有没有解
  • 如果ax+by=1有解,那么gcd(a,b)=1

扩展欧几里得算法

#2020寒假集训#数论入门(Number Theory)代码笔记_第4张图片

#include
#include
#include
#include
using namespace std;
int exgcd(int a,int b,int &x,int &y)
{
	if(b==0) {x=1;y=0;return a;}
	int GCD=exgcd(b,a%b,x,y);
	int t=x;
	x=y;y=t-a%b*y;
	return GCD;
	//返回的是a和b最大公因数,返回之时的x和y满足ax+by=gcd(a,b)
}
int main()
{
	//以下是运用扩展欧几里得算法的样例 
	int a,b,x,y;
	printf("请输入a和b的值:");
	scanf("%d %d",&a,&b);
	printf("\n需要获得的是满足a*x+b*y=gcd(a,b)的x和y\n");
	printf("\n定义后续输出的a,b,x,y,其中a和b输入赋值后传入函数\n");
	printf("\n而x和y定义后直接传入即可,函数的形参对x和y而言是地址\n");
	printf("\n经过调用exgcd()函数,可获得x、y和gcd(a,b)的值\n"); 
	printf("\n即将输出形如a*x+b*y=gcd(a,b)的式子:\n");
	int GCD=exgcd(a,b,x,y);//x和y无需赋值,定义后直接传入即可 
	printf("\n%d*%d+%d*%d=%d\n",a,b,x,y,GCD);
	return 0;
}

#2020寒假集训#数论入门(Number Theory)代码笔记_第5张图片

A的N次方快速幂

int FastPow(int a,int n)
{
	int ans=1;
	while(n)
	{
		if(n&1) ans*=a;//判断n是否为奇数,按位与,奇数二进制末位必为1,此式作用相当于n%2
		a*=a;
		n>>=1;//位移操作,右移一位=除以2
	}
	return ans;
}

质数(素数)

#2020寒假集训#数论入门(Number Theory)代码笔记_第6张图片

欧拉函数

#2020寒假集训#数论入门(Number Theory)代码笔记_第7张图片

素数和欧拉函数的数组准备

bool isprime[maxn];//判断是否为素数 
int primes[maxn],pn;//素数表和素数个数 
int phi[maxn];//phi欧拉函数表 

埃氏筛

素数判断

void Eratosthenes(int n)
{
	memset(isprime,true,sizeof(isprime));
	isprime[0]=isprime[1]=false;
	for(int i=2;i<n;++i)
	{
		if(isprime[i])
		{
			for(int j=2*i;j<=n;j+=i) isprime[j]=false;
		}
	}
}

欧拉函数表

void GetPhi(int n)
{
	memset(phi,0,sizeof(phi));
	phi[1]=1;
	for(int i=2;i<n;++i)
	{
		if(!phi[i])
		{
			for(int j=i;j<n;j+=i)
			{
				if(!phi[j]) phi[j]=j;
				phi[j]-=phi[j]/i;
			}
		}
	}
}

线性筛

素数表

void FastSieve(int n)
{
	memset(isprime,true,sizeof(isprime));
	isprime[0]=isprime[1]=false;
	pn=0;
	for(int i=2;i<=n;++i)
	{
		if(isprime[i]) primes[pn++]=i;
		for(int j=0;j<pn;++j)
		{
			if(i*primes[j]>n) break;
			isprime[i*primes[j]]=false;
			if(i%primes[j]==0) break;
		}
	}
}

素数表+欧拉函数表

void FastPhi(int n)
{
	memset(isprime,true,sizeof(isprime));
	isprime[0]=isprime[1]=false;
	phi[1]=1;
	pn=0;
	for(int i=2;i<=n;++i)
	{
		if(isprime[i])
		{
			primes[pn++]=i;
			phi[i]=i-1;
		}
		for(int j=0;j<pn;++j)
		{
			if(i*primes[j]>n) break;
			isprime[i*primes[j]]=false;
			if(i%primes[j]==0)
			{
				phi[i*primes[j]]=phi[i]*primes[j];
				break;
			}
			phi[i*primes[j]]=phi[i]*(primes[j]-1);
		}
	}
}

其他(更高深的待学习补充……)

#2020寒假集训#数论入门(Number Theory)代码笔记_第8张图片

功能函数部分代码整合

#include
#include
#include
#include
using namespace std;
const int maxn=1e5+10;
const int inf=0x3f3f3f3f;
const long long INF=0x3f3f3f3f3f3f3f3f;


bool isprime[maxn];//判断是否为素数 
int primes[maxn],pn;//素数表和素数个数 
int phi[maxn];//phi欧拉函数表 

//求最大公因数 gcd(a,b)=c 
int gcd(int a,int b) {return a==0?b:gcd(b%a,a);}

//求最小公倍数 lcm(a,b)=c
int lcm(int a,int b) {return a*b/gcd(a,b);}

//扩展欧几里得算法,ax+by=gcd(a,b)求
int exgcd(int a,int b,int &x,int &y)
{
	if(b==0) {x=1;y=0;return a;}
	int GCD=exgcd(b,a%b,x,y);
	int t=x;
	x=y;y=t-a%b*y;
	return GCD;
	//返回的是a和b最大公因数,返回之时的x和y满足ax+by=gcd(a,b)
}

//求快速幂 a的n次方,时间复杂度:O(N)
int FastPow(int a,int n)
{
	int ans=1;
	while(n)
	{
		if(n&1) ans*=a;//判断n是否为奇数,按位与,奇数二进制末位必为1,此式作用相当于n%2
		a*=a;
		n>>=1;//位移操作,右移一位=除以2
	}
	return ans;
}

//求[0,n]范围内的素数判断【埃氏筛】
void Eratosthenes(int n)
{
	memset(isprime,true,sizeof(isprime));
	isprime[0]=isprime[1]=false;
	for(int i=2;i<n;++i)
	{
		if(isprime[i])
		{
			for(int j=2*i;j<=n;j+=i) isprime[j]=false;
		}
	}
}

//求[0,n]范围内的素数表【线性筛】
void FastSieve(int n)
{
	memset(isprime,true,sizeof(isprime));
	isprime[0]=isprime[1]=false;
	pn=0;
	for(int i=2;i<=n;++i)
	{
		if(isprime[i]) primes[pn++]=i;
		for(int j=0;j<pn;++j)
		{
			if(i*primes[j]>n) break;
			isprime[i*primes[j]]=false;
			if(i%primes[j]==0) break;
		}
	}
}

//求[0,n]范围内的phi欧拉函数表【埃氏筛】时间复杂度:O(NlogN)
void GetPhi(int n)
{
	memset(phi,0,sizeof(phi));
	phi[1]=1;
	for(int i=2;i<n;++i)
	{
		if(!phi[i])
		{
			for(int j=i;j<n;j+=i)
			{
				if(!phi[j]) phi[j]=j;
				phi[j]-=phi[j]/i;
			}
		}
	}
}

//求[0,n]范围内的phi欧拉函数表以及素数表【线性筛】时间复杂度:O(N)
void FastPhi(int n)
{
	memset(isprime,true,sizeof(isprime));
	isprime[0]=isprime[1]=false;
	phi[1]=1;
	pn=0;
	for(int i=2;i<=n;++i)
	{
		if(isprime[i])
		{
			primes[pn++]=i;
			phi[i]=i-1;
		}
		for(int j=0;j<pn;++j)
		{
			if(i*primes[j]>n) break;
			isprime[i*primes[j]]=false;
			if(i%primes[j]==0)
			{
				phi[i*primes[j]]=phi[i]*primes[j];
				break;
			}
			phi[i*primes[j]]=phi[i]*(primes[j]-1);
		}
	}
}

实用小技巧:分块打表

HDU-4378-X mod f(x)

HZNU19training-F题

#2020寒假集训#数论入门(Number Theory)代码笔记_第9张图片

题解常规做法应当是【数位DP】,但用【分块打表】却可以快速无脑KO٩(๑>◡<๑)۶

AC代码如下(づ ̄3 ̄)づ╭❤~

#include
#include
#include
#include
using namespace std;
const int maxn=1e5+10;
const int inf=0x3f3f3f3f;
const long long INF=0x3f3f3f3f3f3f3f3f;
int T,a,b;

/*
	打表形成1到每ae6(如1e6、2e6、3e6等)数之间的总和,后续用整除做下标
	所以不足1e6的下标0,sum为0
	注意分块打表:【块太大】代码过长无法提交;【块太小】时间复杂度过大
	思想:用空间换时间 
*/
int sum[]={0,95428,186561,273964,357923,438795,516988,592666,666027,737096,806095,897228,984457,1068251,1148898,1226769,1302141,1375194,1446173,1514990,1581855,1669171,1752886,1833499,1911166,1986220,2059035,2129704,2198383,2265047,2329984,2413838,2494379,2571992,2646896,2719392,2789743,2858080,2924630,2989257,3052160,3132961,3210653,3285645,3358037,3428135,3496170,3562323,3626798,3689474,3750525,3828640,3903809,3976405,4046550,4114501,4180462,4244641,4307251,4368127,4427492,4503070,4575951,4646413,4714477,4780451,4844581,4906971,4967829,5027126,5084970,5158330,5229087,5297507,5363730,5427989,5490370,5551100,5610431,5668264,5724686,5795749,5864428,5930950,5995318,6057901,6118762,6178017,6235854,6292282,6347468,6416462,6483225,6547969,6610705,6671740,6731176,6789058,6845573,6900765,6954793,7045942,7133324,7217267,7298238,7376359,7451901,7525188,7596271,7665191,7732131,7819332,7903158,7983801,8061674,8137010,8209989,8280812,8349662,8416558,8481543,8565293,8645838,8723430,8798508,8871242,8941769,9010332,9077035,9141930,9205050,9285593,9363199,9438009,9510443,9580694,9648877,9715239,9779898,9842802,9904095,9981880,10056856,10129221,10199288,10267274,10333318,10397657,10460350,10521428,10581019,10656301,10728985,10799059,10866960,10932932,10997055,11059473,11120363,11179797,11237788,11310752,11381211,11449286,11515232,11579304,11641607,11702365,11761612,11819414,11875940,11946798,12015315,12081517,12145732,12208192,12268919,12328147,12385962,12442408,12497616,12566393,12632958,12697371,12759893,12820745,12880002,12937821,12994262,13049421,13103432,13170250,13235027,13297720,13358682,13418117,13475977,13532516,13587773,13641793,13694682,13782106,13866076,13947004,14025210,14100803,14174040,14245038,14314021,14380947,14446019,14529813,14610415,14688297,14763678,14836624,14907435,14976195,15043070,15108076,15171368,15251961,15329564,15404599,15477345,15547862,15616379,15683003,15747911,15811043,15872614,15950217,16025027,16097440,16167641,16235766,16302070,16366576,16429517,16490838,16550673,16625756,16698107,16768140,16836156,16902159,16966346,17028895,17089987,17149548,17207734,17280452,17350626,17418595,17484533,17548623,17611005,17671766,17731162,17789201,17845948,17916553,17984678,18050685,18114815,18177141,18237861,18297052,18354881,18411412,18466778,18535402,18601707,18665965,18728405,18789194,18848449,18906195,18962677,19017938,19072027,19138702,19203124,19265635,19326482,19385730,19443553,19500013,19555170,19609185,19662166,19727005,19789801,19850772,19910096,19967975,20024535,20079764,20133785,20186696,20238658,20322597,20403565,20481807,20557471,20630756,20701761,20770688,20837653,20902755,20966010,21046638,21124505,21199886,21272915,21343731,21412464,21479291,21544298,21607602,21669203,21746853,21821937,21894655,21965192,22033727,22100308,22165121,22228315,22289922,22349898,22424773,22497209,22567447,22635611,22701850,22766328,22829202,22890498,22950338,23008770,23081223,23151361,23219386,23285374,23349599,23412111,23473093,23532684,23590877,23647763,23718020,23786035,23852041,23916158,23978539,24039334,24098643,24156609,24213314,24268780,24337060,24403174,24467363,24529756,24590507,24649665,24707495,24764046,24819346,24873479,24939873,25004239,25066837,25127672,25186940,25244759,25301271,25356565,25410686,25463707,25528324,25590933,25651802,25711100,25768962,25825376,25880547,25934669,25987687,26039575,26102480,26163518,26222912,26280781,26337314,26392515,26446544,26499504,26551479,26602369,26683245,26761451,26837125,26910481,26981529,27050529,27117492,27182620,27245924,27307487,27385285,27460604,27533591,27604488,27673208,27740021,27805078,27868454,27930034,27990025,28065008,28137692,28208210,28276739,28343294,28408093,28471204,28532834,28592888,28651439,28723827,28794004,28862093,28928375,28992806,29055572,29116819,29176722,29235135,29292198,29362287,29430277,29496277,29560539,29623050,29683980,29743472,29801754,29858678,29914298,29982292,30048258,30112355,30174775,30235534,30294831,30352769,30409484,30464981,30519347,30585451,30649620,30711925,30772617,30831849,30889653,30946123,31001498,31055711,31108837,31173242,31235760,31296547,31355812,31413586,31470052,31525303,31579509,31632605,31684643,31747292,31808192,31867425,31925208,31981642,32036810,32090863,32143901,32195905,32246926,32307990,32367418,32425302,32481722,32536891,32590908,32643839,32695804,32746742,32796782,32874968,32950587,33023953,33095113,33164127,33231148,33296316,33359587,33421118,33480907,33556228,33629225,33700084,33768904,33835776,33900799,33964089,34025744,34085770,34144108,34216817,34287282,34355794,34422414,34487205,34550325,34611889,34671945,34730521,34787529,34857718,34925813,34992032,35056488,35119231,35180431,35240221,35298620,35355655,35411317,35479293,35545295,35609550,35672064,35732999,35792513,35850682,35907566,35963231,36017597,36083617,36147675,36210061,36270874,36330182,36388092,36444784,36500333,36554676,36607817,36671993,36734324,36795077,36854284,36912058,36968561,37023907,37078147,37131327,37183292,37245833,37306604,37365847,37423645,37480077,37535283,37589462,37642603,37694729,37745713,37806644,37865914,37923694,37980059,38035222,38089202,38142136,38194179,38245263,38295232,38354701,38412552,38468981,38524132,38578081,38630964,38682866,38733828,38783911,38832914,38908583,38981897,39053029,39122221,39189297,39254476,39317805,39379416,39439158,39497335,39570288,39641115,39709901,39776869,39841927,39905236,39966831,40026905,40085269,40142121,40212631,40281128,40347739,40412657,40475820,40537361,40597348,40655927,40712973,40768651,40836794,40903033,40967460,41030286,41091552,41151325,41209639,41266742,41322423,41376852,41442902,41507137,41569660,41630662,41690170,41748361,41805197,41860855,41915224,41968476,42032593,42095005,42155775,42215075,42273030,42329738,42385199,42439557,42492725,42544806,42607199,42667971,42727171,42784944,42841453,42896829,42951025,43004191,43056253,43107279,43168113,43227382,43285164,43341612,43396821,43450971,43504065,43556222,43607184,43657184,43716428,43774223,43830647,43885764,43939671,43992660,44044641,44095641,44145637,44194636,44252494,44308986,44364108,44418014,44470872,44522725,44573633,44623628,44672601,44720629,44794005,44865198,44934349,45001584,45066911,45130333,45191976,45251787,45310025,45366844,45437696,45506553,45573530,45638699,45702135,45763831,45823880,45882265,45939191,45994799,46063347,46129966,46194870,46258127,46319762,46379779,46438321,46495363,46551000,46605449,46671687,46736169,46799035,46860364,46920203,46978609,47035651,47091288,47145705,47198975,47263262,47325865,47386941,47446554,47504820,47561735,47617432,47671839,47725059,47777248,47839686,47900480,47959851,48017897,48074653,48130154,48184527,48237785,48289914,48340949,48401734,48460940,48518784,48575385,48630774,48684983,48738184,48790253,48841257,48891281,48950568,49008406,49064893,49120186,49174403,49227508,49279587,49330650,49380748,49429749,49487593,49544003,49599175,49653214,49706263,49758231,49809251,49859258,49908319,49956416,50012939,50068106,50122054,50174919,50226849,50277769,50327748,50376753,50424815,50471934,50543022,50612052,50679125,50744445,50807863,50869439,50929201,50987429,51044220,51099607,51168361,51235216,51300300,51363750,51425403,51485421,51543742,51600619,51656190,51710497,51777039,51841877,51905040,51966703,52026746,52085255,52142191,52197819,52252283,52305518,52369942,52432732,52493946,52553782,52612187,52669180,52724716,52779054,52832283,52884417,52946983,53008002,53067584,53125847,53182737,53238405,53292758,53345986,53398129,53449198,53510010,53569397,53627408,53684177,53739690,53794086,53847263,53899332,53950433,54000471,54059725,54117567,54174125,54229534,54283787,54336960,54389024,54440074,54490073,54539065,54596858,54653321,54708606,54762796,54815894,54867984,54919003,54969042,55018064,55066115,55122511,55177648,55231720,55284761,55336740,55387782,55437779,55486799,55534858,55581915,55637110,55691089,55743955,55795845,55846788,55896814,55945777,55993821,56040967,56087100,56156071,56223092,56288279,56351665,56413249,56473056,56531247,56587992,56643393,56697604,56764416,56829445,56892787,56954471,57014495,57072818,57129649,57185152,57239377,57292496,57357282,57420361,57481948,57542029,57600539,57657469,57713058,57767453,57820606,57872728,57935511,57996697,58056498,58114926,58171898,58227468,58281754,58334967,58387038,58438097,58499132,58558706,58616928,58673870,58729547,58783867,58837026,58889151,58940211,58990253,59049654,59107613,59164359,59219899,59274282,59327409,59379443,59430529,59480562,59529673,59587580,59644141,59699522,59753844,59807078,59859126,59910056,59960092,60009102,60057199,60113684,60168991,60223138,60276243,60328395,60379431,60429373,60478378,60526472,60573660,60628848,60682884,60735882,60787876,60838961,60888926,60937892,60985975,61033028,61079255,61133247,61186172,61238101,61288972,61338974,61387988,61435986,61483093,61529229,61574510};

int f(int x)
{
	if (x==0) return 0;
	return f(x/10)+x%10;
}

int work(int x)
{
	int ans=sum[x/1000000];
	for(int i=x/1000000*1000000+1;i<=x;++i) if(i%f(i)==0) ans++;
	//求对应的ae6+1到本身这个范围内的总量 
	return ans;
}

int main()
{
	scanf("%d",&T);
	for(int i=1;i<=T;++i)
	{
		scanf("%d %d",&a,&b);
		printf("Case %d: %d\n",i,work(b)-work(a-1));
		//求总量的区间范围是[a,b],打表相当于求了前缀和
		//work(a)是1到a的总量,但a在需求区间内,不能被删去 
	}
}

中间一长串的sum数组就是【分块打表】的关键

打表代码如下❥(ゝω・✿ฺ)

#include
#include
#include
#include
using namespace std;
const int maxn=1e5+10;
const int inf=0x3f3f3f3f;
const long long INF=0x3f3f3f3f3f3f3f3f;
int T,a,b;

int f(int x)
{
	if (x==0) return 0;
	return f(x/10)+x%10;
}

int main()
{
	int sum=0;
	for(int i=1;i<=1e9;++i)
	{
		if(i%f(i)==0) sum++;
		if(i%1000000==0) printf("%d,",sum);
	}
	return 0;
}

运行打表程序,将生成如下结果,复制粘贴到AC代码的sum[]{};的大括号中即可啦ヾ(@^ ▽ ^@)ノ

#2020寒假集训#数论入门(Number Theory)代码笔记_第10张图片

或者用freopen语句将打表结果保存在一个txt文件中

但务必注意运行后需等几秒再关闭运行窗口,不然打表还未结束,txt中数据不完整

保存到txt文件的代码如下(。◕ˇ∀ˇ◕)

#include
#include
#include
#include
using namespace std;
const int maxn=1e5+10;
const int inf=0x3f3f3f3f;
const long long INF=0x3f3f3f3f3f3f3f3f;
int T,a,b;

int f(int x)
{
	if (x==0) return 0;
	return f(x/10)+x%10;
}

int main()
{
	freopen("1.txt","w",stdout);
	int sum=0;
	for(int i=1;i<=1e9;++i)
	{
		if(i%f(i)==0) sum++;
		if(i%1000000==0) printf("%d,",sum);
	}
	return 0;
}

仅比前文直接打印的程序代码多出如下一行语句

freopen("1.txt","w",stdout);

你可能感兴趣的:(2020寒假集训)