NOIP大纲整理:(二)文件读写与数论基础

文件读入读出

假设题目名为“add”,那么文件夹名为“add”,c++程序名为“add.cpp”,读入文件名为“add.in”,输出文件名为“add.out”。四个的拼写均不可有误,包括大小写差异。千万不要调试后就忘记修改文件读入读出了。 

#include<cstdio>
int main()
{
   freopen("add.in","r",stdin);//read
   freopen("add.out","w",stdout);//write
}

数论算法

1、线性筛(素数):暂时代码是转载的,以后有机会会更新,看不懂请跳过

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
const int maxn=200005;
int prime[maxn];
bool not_prime[maxn];
int main()
{
    int n,cnt=0;
   scanf("%d",&n);
   memset(not_prime,0,sizeof(not_prime));
   not_prime[1]=true;
    for(inti=2;i<=n;i++)
    {
       if(!not_prime[i])
           prime[++cnt]=i;
        for(intj=1;j<=cnt;j++)
        {
           if(prime[j]*i>n)    break;
           not_prime[prime[j]*i]=true;
            if(i%prime[j]==0) break;
        }
    }
    for(inti=1;i<=cnt;i++)
       printf("%d ",prime[i]);
    return 0;
}

2、埃氏筛(素数+读写外挂)暂时代码是转载的,以后有机会会更新,看不懂请跳过

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
inline int read()
{
    char c;
    c=getchar();
   for(;c>'9'||c<'0';c=getchar());
    int sum=0;
   for(;c<='9'&&c>='0';c=getchar())sum=sum*10+c-48;
    return sum;
}
int n,m;
bool f[10010000];
int main()
{
   n=read(),m=read();
   memset(f,true,sizeof(f));
   f[0]=f[1]=false;
    for(inti=2;i<=n;i++)
    if(f[i])
    for(intj=2;i*j<=n;f[i*j]=false,j++);
    for(inti=1;i<=m;i++)
    {
        int x;
        x=read();
       if(f[x])printf("Yes\n");
        elseprintf("No\n");
    }
    return 0;
}

3、拓展欧几里得算法(求逆元公式) 暂时代码是转载的,以后有机会会更新,看不懂请跳过

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
int x,y;
int exgcd(int a,int b)
{
    if(!b)
    {
        x=1;
        y=0;
        return a;
    }
    else
    {
        int t;
        intd=exgcd(b,a%b);
        t=x;
        x=y;
        y=t-a/b*x;
        return d;
    }
}
int main()
{
    int a,b;
   scanf("%d%d",&a,&b);
    exgcd(a,b);
// cout<<__gcd(a,b)<<endl;
   cout<<x<<" "<<y<<endl;
    return 0;
}

4、GCD&LCM(求最小公倍数与最大公约数) 暂时代码是转载的,以后有机会会更新,看不懂请跳过

#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
int gcd(int a,int b)
{
    if(!b) returna;
    else returngcd(b,a%b);
}
int lcm(int a,int b)
{
    returna/gcd(a,b)*b;
}
int main()
{
    int a,b;
   scanf("%d%d",&a,&b);
   cout<<gcd(a,b)<<" "<<lcm(a,b)<<endl;
    return 0;
}

5、分解质因数 暂时代码是转载的,以后有机会会更新,看不懂请跳过

#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
int main()
{
    long long n;
   scanf("%lld",&n);
    for(long longi=2;i<=n;i++)
    {
        while(n!=i)
        {
           if(n%i==0)
            {
                printf("%lld*",i);
               n=n/i;             
            }
            elsebreak;
        }
    }
   printf("%lld",n);
    return 0;
}

6、大数翻倍法 暂时代码是转载的,以后有机会会更新,看不懂请跳过

#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
int a[233],mo[233];
int gcd(int a,int b)
{
    if(!b) returna;
    else returngcd(b,a%b);
}
int lcm(int a,int b)
{
    returna/gcd(a,b)*b;
}
int main()
{
    int n;
   scanf("%d",&n);
    for(inti=1;i<=n;i++)
       scanf("%d%d",&a[i],&mo[i]);
    intans=0,nowmo=1;
    for(inti=1;i<=n;i++)
    {
        intother=a[i],othermo=mo[i];
       if(othermo>nowmo)
        {
           swap(ans,other);
           swap(nowmo,othermo);
        }
       while(ans%othermo!=other)
           ans+=nowmo;
       nowmo=lcm(nowmo,othermo);
    }
   printf("%d",ans);
}

7、快速幂 

模板题:luogu1226:快速幂

[HNOI2008]越狱

luogu3390:矩阵快速幂

8、位运算 

位运算

示例

功能

x >> 1

(101101->10110)

去掉最后一位

x  << 1

(101101->1011010)

在最后加一个0

x << 1+1

(101101->1011011)

在最后加一个1

x  | 1

(101100->101101)

把最后一位变成1

x | 1-1

(101101->101100)

把最后一位变成0

x  ^ 1

(101101->101100)

最后一位取反

x | (1 << (k-1))

(101001->101101,k=3)

把右数第k位变成1

x  & !(1 << (k-1))

(101101->101001,k=3)

把右数第k位变成0

x ^ (1 << (k-1))

(101001->101101,k=3)

右数第k位取反

x  & 7

(1101101->101)

取末三位

x & (1<< k -1)

(1101101->1101,k=5)

取末k位

x  >> (k-1) & 1

(1101101->1,k=4)

取右数第k位

x | (1 << k-1)

(101001->101111,k=4)

把末k位变成1

x  ^ (1 << k-1)

(101001->100110,k=4)

末k位取反

x & (x+1)

(100101111->100100000)

把右边连续的1变成0

x  | (x+1)

(100101111->100111111)

把右起第一个0变成1

x | (x-1)

(11011000->11011111)

把右边连续的0变成1

(x  ^ (x+1)) >> 1

(100101111->1111)

取右边连续的1

x & (x ^ (x-1))

(100101000->1000)

去掉右起第一个1的左边

猜你喜欢

转载自blog.csdn.net/liusu201601/article/details/81430284