多校 2009 3

D n 然后n个数  (1<=数<=n)  要求是变成序列1-n  按顺序  可以交换相邻2个数字a  b  花费是 a+b 求最小花费

线段数维护  区间里的数的数目  然后区间的和  每个数 查询比他小的数目的个数和 他们的和 那么花费就是  数目 *a + sum   long long

#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<iostream>

using namespace std;

#define MAXN 100010
#define inf  1000000007
#define ll long long
struct node
{
    int l,r,w;
    ll sum;
}tree[MAXN<<2];
void Build(int l,int r,int a)
{
    tree[a].l=l;
    tree[a].r=r;
    tree[a].w=0;
    tree[a].sum=0;
    if(l==r)
        return ;

    int mid=(l+r)>>1;
    Build(l,mid,a<<1);
    Build(mid+1,r,a<<1|1);
}
int num;
ll Ques(int l,int r,int a1,int b1,int a)
{
    if(a1<=l&&r<=b1)
    {
        num=num+tree[a].w;
        return tree[a].sum;
    }
    int mid=(l+r)>>1;
    ll ans=0;
    if(a1<=mid)
        ans=ans+Ques(l,mid,a1,b1,a<<1);
    if(b1>mid)
        ans=ans+Ques(mid+1,r,a1,b1,a<<1|1);
    return ans;
}
ll z[MAXN];
int ind[MAXN];
void Update(int l,int r,int a1,int a)
{
    if(l==r)
    {
        tree[a].w=1;
        tree[a].sum=l;
        return ;
    }
    int mid=(l+r)>>1;
    if(a1<=mid)
        Update(l,mid,a1,a<<1);
    else
        Update(mid+1,r,a1,a<<1|1);
    tree[a].w=tree[a<<1].w+tree[a<<1|1].w;
    tree[a].sum=tree[a<<1].sum+tree[a<<1|1].sum;
}
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        Build(1,n,1);
        for(int i=1;i<=n;i++)
            scanf("%lld",&z[i]);

        ll ans=0;
        for(int i=n;i>=1;i--)
        {
            num=0;
            ll sum=Ques(1,n,1,z[i],1);
            ans=ans+sum+num*z[i];//+num*z[i];
            //printf("%d
",ans);
            Update(1,n,z[i],1);
        }
        printf("%lld
",ans);
    }
    return 0;
}
View Code

H

f(n)=f(n-1)+2*f(n-2)+1

f(1)=1

f(2)=2

#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<iostream>

using namespace std;

#define MAXN 100010
#define inf  1000000007
#define ll long long

struct node
{
    ll z[3][3];
}a,b;

node mou(node a,node b,int c)
{
    node ans;
    memset(ans.z,0,sizeof(ans.z));
    for(int i=0;i<3;i++)
    {
        for(int j=0;j<3;j++)
        {
            ll sum=0;
            for(int k=0;k<3;k++)
                sum=sum+(a.z[i][k]*b.z[k][j])%c;
            ans.z[i][j]=sum;
        }
    }
    return ans;
}
node Quick(node a,int b,int c)
{
    node ans;
    memset(ans.z,0,sizeof(ans.z));
    for(int i=0;i<3;i++)
        ans.z[i][i]=1;
    while(b>0)
    {
        if(b&1)
            ans=mou(ans,a,c);
        b>>=1;
        a=mou(a,a,c);
    }
    return ans;
}
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF&&n)
    {
        if(n==1)
            printf("1
");
        else if(n==2)
            printf("2
");
        else
        {
             memset(a.z,0,sizeof(a.z));
             a.z[0][1]=2;
             a.z[1][0]=a.z[1][1]=a.z[2][1]=a.z[2][2]=1;
             b=Quick(a,n-2,200907);
             printf("%d
",(b.z[0][1]+2*b.z[1][1]+b.z[2][1])%200907);
        }
    }
    return 0;
}
View Code

 C

f(n)=(n%10)^f(n/10)   f(0)=1  

欧拉降幂 A^B%C=A^(B%ph(C)+ph(C)) %C     条件B>=ph(C)

#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<iostream>
#include<math.h>

using namespace std;

#define MAXN 100010
#define inf  1000000007
#define ll long long

ll ph(ll a)
{
    ll b=a,c=a,en;
    en=sqrt(a);
    for(ll i=2;i<=en;i++)
    {
        if(c%i==0)
        {
            b=b/i*(i-1);
            while(c%i==0)
                c=c/i;
        }
    }
    if(c>1)
        b=b/c*(c-1);
    return b;
}
ll Quick(ll a,ll b,ll c)
{
    ll ans=1;
    while(b>0)
    {
        if(b&1)
            ans=(ans*a)%c;
        b>>=1;
        a=(a*a)%c;
    }
    return ans;
}
ll calc(ll a,ll b,ll mod)
{
    ll ans=1;
    for(ll i=1;i<=b;i++)
    {
        ans=ans*a;
        if(ans>=mod)
            return ans;
    }
    return ans;
}
ll f(ll n,ll m)
{
    if(n<10)
        return n;
    ll b=f(n/10,ph(m));//
    ll c=calc(n%10,b,m);
    if(c>=m)
    {
        ll ans=Quick(n%10,b,m);
        if(ans==0)
            ans=ans+m;
        return ans;
    }
    return c;
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        ll n,m;
        scanf("%lld%lld",&n,&m);
        printf("%lld
",f(n,m));
    }
    return 0;
}
View Code

A  页面置换算法 最佳置换算法 大概就是 最久不会使用到的被丢到

先声明一下 我下面的代码是WA的   但是我觉得我是对的 我维护了第i个数字的下次使用的下标然后放到优先队列里维护 不知到为什么错

#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<iostream>
#include<math.h>
#include<queue>

using namespace std;

#define MAXN 100010
#define inf  1000000007
#define ll long long

int z[MAXN];
int nex[MAXN];
bool vis[MAXN];
int ind[MAXN];
struct node
{
    int w,w1;
    friend bool operator < (node a,node b)
    {
        return a.w>b.w;
    }
};
priority_queue<node>q1;

int main()
{
    int c,a,b;
    while(scanf("%d%d%d",&c,&a,&b)!=EOF)
    {
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=b;i++)
            scanf("%d",&z[i]);
        for(int i=0;i<=b;i++)
            ind[i]=inf;
        int ans=0;
        for(int i=b;i>=1;i--)
        {
            nex[i]=ind[z[i]];
            ind[z[i]]=i;
        }
        while(!q1.empty())
            q1.pop();

        for(int i=1;i<=b;i++)
        {
            int d=z[i];
            if(vis[d])
                ;
            else
            {
                if(q1.size()>=c)
                {
                    node n1=q1.top();
                    q1.pop();
                    vis[n1.w1]=0;
                    node n;
                    n.w=nex[i]-i;
                    n.w1=z[i];
                    q1.push(n);
                    vis[d]=1;
                    ans++;
                }
                else
                {
                    node n;
                    n.w=nex[i]-i;
                    n.w1=z[i];
                    q1.push(n);
                    vis[d]=1;
                    ans++;
                }
            }
        }
        printf("%d
",ans);
    }
    return 0;
}
View Code

G

裸的莫比乌斯反演

#include<stdio.h>

#define MAXN 100000
bool    mark[100005];
int     prim[100005];
int     mobi[100005];

long long min(long long a,long long b)
{
    return  a<b?a:b;
}

int main()
{
    int T,i,j,k;
    mobi[1]=1;
    j=0;
    for(i=2;i<=MAXN;i++)
    {
        if(mark[i]==false)
        {
            prim[j++]=i;
            mobi[i]=-1;
        }

        for(k=0;k<j;k++)
        {
            if(i*prim[k]>MAXN)
                break;

            mark[i*prim[k]]=true;
            if(i%prim[k]==0)
            {
                mobi[i*prim[k]]=0;
                break;
            }
            else
                mobi[i*prim[k]]=-mobi[i];
        }
    }

    scanf("%d",&T);

    j=1;

    while(T--)
    {
        long long a,b,c,d;
        long long sum,sum2;


        scanf("%lld%lld",&b,&d);
        a=c=k=1;
        sum=0;
        sum2=0;
        a=b/k;
        c=d/k;

        for(i=1;i<=min(a,c);i++)
            sum=sum+mobi[i]*(a/i)*(c/i);
        for(i=1;i<=min(a,c);i++)
            sum2=sum2+mobi[i]*(min(a,c)/i)*(min(a,c)/i);

        printf("%lld
",sum);
    }

    return 0;
}
View Code

J 多重背包   2进制优化 以前写过 就不写了

原文地址:https://www.cnblogs.com/cherryMJY/p/6887965.html