比赛模板

线性筛法:

#include<bits/stdc++.h>
using namespace std;
#define MAXN 100005
#define MAXL 1299710
int prime[MAXN];
int check[MAXL];
int tot = 0;
void solve_prime()
{
    memset(check, 0, sizeof(check));
    for (int i = 2; i < MAXL; ++i)
    {
        if(!check[i])
            prime[tot++] = i;
        for (int j = 0; j < tot; ++j)
        {
            if (i * prime[j] > MAXL)
                break;
            check[i*prime[j]] = 1;
            if (i % prime[j] == 0)
                break;
        }
    }
}

快速幂取模: 

typedef long long ll;
ll powerMod(ll x, ll n, ll mod)
{
    ll ans = 1;
    while (n > 0){
        if  (n & 1)
            ans = (ans * x) % mod;
        x = (x * x) % mod;
        n >>= 1;
    }
    return ans;
}

矩阵快速幂:

// 矩阵快速幂Sn=11*Sn-1-10*Sn-2+a,注意运算溢出的问题
#include<bits/stdc++.h>
using namespace std;
int mod;
typedef struct mat
{
    int m[3][3];
}mat;
mat mul(mat a,mat b)
{
    mat t;
    memset(t.m,0,sizeof(t.m));
    for(int i=0;i<3;i++)
        for(int j=0;j<3;j++)
        for(int k=0;k<3;k++)
        t.m[i][j]=((long long)t.m[i][j]+(long long)a.m[i][k]*b.m[k][j]+mod)%mod;
    return t;
}
mat pow_(mat a,int n)
{
    mat b;
    memset(b.m,0,sizeof(b.m));
    for(int i=0;i<3;i++) b.m[i][i]=1;
    while(n>0)
    {
        if(n&1) b=mul(b,a);
        a=mul(a,a);
        n>>=1;
    }
    return b;
}
int main()
{
    int a,n;
    while(scanf("%d%d%d",&a,&n,&mod)==3){
        mat ans;
        ans.m[0][0]=11,ans.m[0][1]=-10,ans.m[0][2]=a;
        ans.m[1][0]=1,ans.m[1][1]=0,ans.m[1][2]=0;
        ans.m[2][0]=0,ans.m[2][1]=0,ans.m[2][2]=1;
        ans=pow_(ans,n-1);
        printf("%d\n",(ans.m[0][0]*a+ans.m[0][2]+mod)%mod);
    }
}

组合数取模:

ll qpow(ll n, ll m, ll p)
{
    ll res=1;
    while(m)
    {
        if(m%2!=0)
        {
            res*=n;
            res%=p;
        }
        n*=n;
        n%=p;
        m/=2;
    }
    return res;
}

ll C(ll n,ll m,ll p)
{
    if(m>n)
        return 0;
    ll a=1,b=1;
    while(m)
    {
        a*=n;
        a%=p;
        n--;
        b*=m;
        m--;
        b%=p;
    }
    return a*qpow(b,p-2,p)%p;
}

ll Lucas(ll n,ll m,ll p) // C(n,m)%p
{
    if(m==0)
        return 1;
    return Lucas(n/p,m/p,p)*C(n%p,m%p,p)%p;
}

并查集:

const int maxn=1e5+5;
int father[maxn];
void makeSet()
{
    for(int i=0;i<maxn;i++)
        father[i] = i;
}
int findRoot(int x)
{
    int root = x;
    while (root != father[root])
    {
        root = father[root];
    }
    // 路径压缩,优化
    while (x != root)
    {
        int tmp = father[x];
        father[x] = root;
        x = tmp;
    }
    return root;
}
void Union(int x,int y)
{
    int a, b;
    a = findRoot(x);
    b = findRoot(y);
    father[a] = b;
}

KMP: 

void getNext(string short_string)
{
    int len = short_string.size();
    int k = -1,j = 0;
    Next[0] = k;
    while (j < len)
    {
        if(k == -1 || short_string[k] == short_string[j])
        {
            j++,k++;
            if (short_string[j] == short_string[k])
            {
                Next[j] = Next[k];
            }
            else
            {
                Next[j] = k;
            }
        }
        else
            k = Next[k];
    }
}
int kmp(string short_string,string long_string)
{
    int ans = 0;
    int len = long_string.size();
    int j = 0,i = 0;
    while (i < len)
    {
        if (j == -1 || long_string[i] == short_string[j])
        {
            i++,j++;
            if (j >= short_string.size())  //如果只匹配一次,直接break
            {
                ans++;
                j = Next[j];
            }
        }
        else
        {
            j = Next[j];
        }
    }
    return ans;
}

欧拉函数:

int euler_phi(int n){ //单个值
    int m = (int)sqrt(n + 0.5);
    int ans = n;
    for (int i = 2;i <= m;i++){
        if (n%i == 0){       //如果存在素因子
            ans = ans/i*(i-1); 
            while (n%i == 0) n/=i;
        }
    }
    if(n > 1) ans = ans/n*(n-1); //考虑n本身
    return ans;
}
 
void phi_table(int n,int *phi){ //欧拉表
    for (int i = 1;i <= n;i++) phi[i] = i;
    for(int i = 2;i <= n;i++){
        if(phi[i] == i){   //类似于Eratosthenes筛法这里
            for(int j = i;j <= n;j+=i){
                phi[j] = phi[j]/i*(i-1);
            }
        }
    }       
}

扩展欧几里得:

ll gcd(ll a,ll b) {
    return b == 0 ? a : gcd(b, a % b);
}
求x在模为mod时的逆元:
exgcd(x,mod,x,y)
求出后,第三个参数就是逆元。
mod可以不为质数
void exgcd(ll a, ll b, ll &d, ll &x, ll &y) {
    if(!b) d=a,x=1,y=0;
    else exgcd(b, a % b, d, y, x),y -= x * (a / b);
}

树状数组: 

 
/*
单点更新,区间查询,(也可区间更新加),逆序对等等
*/
int lowerbit(int x) {
    return x & -x;
}
 
void add(int p, int x) {
    while (p < maxn) {
        d[p] += x;
        p += lowerbit(p);
    }
}
int sum(int p) {
    int res = 0;
    while (p) {
        res += d[p];
        p -= lowerbit(p);
    }
    return res;
}

最小生成树:

// 紫书上的Kruskal算法模板
#include<bits/stdc++.h>
using namespace std;
const int maxn=50*99+2;
int n,m,u[maxn],v[maxn],w[maxn],p[maxn],r[maxn];
bool cmp(const int i,const int j)//间接排序函数
{
    return w[i]<w[j];//排序的关键字是对象的代号,而不是对象本身
}
int Find(int x)
{
    while(x!=p[x]) x=p[x];
    return x;
}
int Kruskal()
{
    int ans=0;
    for(int i=1;i<=n;i++) p[i]=i;//初始化并查集
    for(int i=1;i<=m;i++) r[i]=i;//初始化序号
    sort(r+1,r+m+1,cmp);//给边排序
    for(int i=1;i<=m;i++)
    {
        int e=r[i];
        int x=Find(u[e]),y=Find(v[e]);//找出当前边两个端点所在的集合编号
        if(x!=y) ans+=w[e],p[x]=y;//如果在不同集合,合并
    }
    return ans;
}
int main()
{
    while(scanf("%d",&n)==1&&n)
    {
        m=n*(n-1)/2;
        for(int i=1;i<=m;i++) scanf("%d%d%d",&u[i],&v[i],&w[i]);
        printf("%d\n",Kruskal());
    }
    return 0;
}

最短路:

// Dijkstra算法
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 2e5 + 5;
const ll INF = 1e18;
int n,m,k,a,b,c;
struct EGE{int to;ll w;int k;
    bool operator < (const EGE& x) const{
        return w > x.w;
    }
};
vector<EGE> g[maxn];
ll dis[maxn][10];
ll dijkstra(int s){
    priority_queue<EGE> q;
    q.push({s,0,0});
    for(int i=1;i<=n;i++)
        for(int j=0;j<=k;j++) dis[i][j] = INF;
    dis[1][0] = 0;
    while(!q.empty()){
        EGE now = q.top();q.pop();
        int u = now.to;
        int tim = now.k;
        ll w = now.w;
        if(w > dis[u][tim]) continue;
        if(u == n) return w;
        for(int i=0;i<g[u].size();i++){
            int v = g[u][i].to;
            if(dis[v][tim] > w + g[u][i].w){
                dis[v][tim] = w + g[u][i].w;
                q.push({v,dis[v][tim],tim});
            }
            if(dis[v][tim+1] > w + 1 && tim+1 <= k){
                dis[v][tim+1] = w + 1;
                q.push({v,dis[v][tim+1],tim+1});
            }
        }
    }
    return 0;
}
int main()
{
    scanf("%d %d %d",&n,&m,&k);
    for(int i=1;i<=m;i++){
        scanf("%d %d %d",&a,&b,&c);
        g[a].push_back({b,c,0});
        g[b].push_back({a,c,0});
    }
    cout << dijkstra(1);
    return 0;
}

欧拉回路+并查集+字典树:

#include<bits/stdc++.h>
using namespace std;
const int maxn=5e5;
int color=0,degree[maxn+1]={0},fa[maxn+1];
struct node
{
    bool flag;
    int id;
    node* next[27];
    node()
    {
        flag=false;
        id=0;
        memset(next,0,sizeof(next));
    }
}root;
int Find(int x)
{
    while(x!=fa[x]) x=fa[x];
    return x;
}
void mer(int a,int b)
{
    int pa=Find(a);
    int pb=Find(b);
    fa[pb]=pa;
}
int Hash(char *s)
{
    node* p=&root;
    int len=0;
    while(s[len]!='\0')
    {
        int index=s[len++]-'a';
        if(!p->next[index]) p->next[index]=new node;
        p=p->next[index];
    }
    if(p->flag) return p->id;
    else
    {
        p->flag=true;
        p->id=++color;
        return p->id;
    }
}
int main()
{
    char a[11],b[11];
    for(int i=1;i<=maxn;i++) fa[i]=i;
    while(~scanf("%s%s",a,b))
    {
        int i=Hash(a);
        int j=Hash(b);
        degree[i]++;
        degree[j]++;
        mer(i,j);
    }
    int Root=Find(1);
    int cnt=0;
    for(int i=1;i<=color;i++)
    {
        if(degree[i]&1) cnt++;
        if(cnt>2||Find(i)!=Root)
        {
            printf("Impossible\n");
            return 0;
        }
    }
    printf("%s\n",cnt==1?"Impossible":"Possible");
}

线段树:

#include<bits/stdc++.h>
using namespace std;
#define INF 0x7fffffff
typedef long long ll;
typedef pair<int,int> P;
const int maxnode=1<<17;
int n,m;
//编号从1到n
int _min,_max,_sum;//全局变量,目前位置的最小值、最大值以及累加和
int op,qL,qR,v;
//m个操作
//1 L R v
//2 L R
struct IntervalTree
{
    int sumv[maxnode],minv[maxnode],maxv[maxnode],addv[maxnode];

    //维护信息
    //维护结点o,它对应的区间是[L,R]
    void maintain(int o,int L,int R){
        int lc=2*o,rc=2*o+1;
        sumv[o]=minv[o]=maxv[o]=0;
        if(R>L){
            //考虑左右子树
            sumv[o]=sumv[lc]+sumv[rc];
            minv[o]=min(minv[lc],minv[rc]);
            maxv[o]=max(maxv[lc],maxv[rc]);
        }
        //考虑add操作
        minv[o]+=addv[o];
        maxv[o]+=addv[o];
        sumv[o]+=addv[o]*(R-L+1);
    }

    //修改操作
    void update(int o,int L,int R){
        int lc=2*o,rc=2*o+1;
        if(qL<=L&&R<=qR){
            //递归边界
            addv[o]+=v;//累加边界的add值
        }
        else{
           int M=L+(R-L)/2;
           if(qL<=M) update(lc,L,M);
           if(qR>M) update(rc,M+1,R);
        }
        //递归结束前重新计算本结点的附加信息
        maintain(o,L,R);
    }

    void query(int o,int L,int R,int add){
        if(qL<=L&&R<=qR){
            //递归边界:用边界区间的附加信息更新答案
            _sum+=sumv[o]+add*(R-L+1);
            _min=min(_min,minv[o]+add);
            _max=max(_max,maxv[o]+add);
        }
        else{
            //不递归统计,累加参数add
            int M=L+(R-L)/2;
            if(qL<=M) query(2*o,L,M,add+addv[o]);
            if(qR>M) query(2*o+1,M+1,R,add+addv[o]);
        }
    }
};

IntervalTree tree;

int main()
{
    while(scanf("%d%d",&n,&m)==2){
        memset(&tree,0,sizeof(tree));
        while(m--){
            scanf("%d%d%d",&op,&qL,&qR);
            if(op==1){
                scanf("%d",&v);
                tree.update(1,1,n);
            }
            else{
                _sum=0,_min=INF,_max=-INF;
                tree.query(1,1,n,0);
                printf("%d %d %d\n",_sum,_min,_max);
            }
        }
    }
    return 0;
}

容斥原理+莫比乌斯函数:

const int N=1000005;
bool check[N+5];
int prime[N+5];
int phi[N+5];
int mu[N+5];
void miu()
{
    memset(check,false,sizeof(check));
    mu[1]=1;
    int tot=0;
    for(int i=2;i<=N;i++)
    {
        if(!check[i])
        {
            prime[tot++]=i;
            mu[i]=-1;
        }
        for(int j=0;j<tot;j++)
        {
            if(i*prime[j]>N) break;
            check[i*prime[j]]=true;
            if(i%prime[j]==0)
            {
                mu[i*prime[j]]=0;
                break;
            }
            else
                mu[i*prime[j]]=-mu[i];
        }
    }
}
int main()
{
    miu();
    int t;
    scanf("%d",&t);
    while(t--)
    {
        LL n;
        scanf("%lld",&n);
        LL ans=0;
        for(LL i=1;i<N&&i*i<=n;i++)
        {
            LL temp=n/(LL)(i*i);
            ans+=mu[i]*temp;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值