10.14 上午 考试

T1

定义 tot=n+m  假设n是较小的

那么每次操作相当于 n=n*2  m=m-(tot-m)=2*m-tot

即直接在mod n+m意义下 快速幂即可

 

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <map>
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
inline int read()
{
    char q=getchar();int ans=0;
    while(q<'0'||q>'9')q=getchar();
    while(q>='0'&&q<='9'){ans=ans*10+q-'0';q=getchar();}
    return ans;
}

ll qpow(ll a,ll ci,ll mod)
{
    ll ans=1;
    while(ci)
    {
        if(ci&1)
            ans=ans*a%mod;
        a=a*a%mod;
        ci>>=1;
    }
    return ans;
}

int ci;
ll n,m;

int main(){

    scanf("%lld%lld%d",&n,&m,&ci);
    ll tt=n*qpow(2,ci,n+m)%(n+m);
    cout<<min(tt,n+m-tt);
}
T1

 

我在考试的时候发现了 对于每一个n、m,它们最后不是一个变成0,就是循环

然后我就用了map...

T2

直接预处理出来每一个"坏对"

这个可以通过枚举$a_i$的倍数来实现

不细讲了

我只是忘了判$a_i<=K$...

 

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#define INF 0x7fffffff
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
inline int read()
{
    char q=getchar();int ans=0;
    while(q<'0'||q>'9')q=getchar();
    while(q>='0'&&q<='9'){ans=ans*10+q-'0';q=getchar();}
    return ans;
}
const int N=100006;

struct son
{
    int l,r;
}ji[N*3];
int con;

int n,K;
int a[N],maxa;

int q[N];
vector<int> L[N],R[N];

void chu()
{
    int order;
    for(int i=1;i<=n;++i)
    {
        if(a[i]<=K)//鑰冭瘯娌℃墦鍟婂晩鍟婂晩
        {
            q[a[i]]=i;
            continue;
        }
        order=0;
        for(int j=K;j<=maxa;j+=a[i])
            if(order<q[j])
                order=q[j];
        if(order)
        {
            ++con;
            ji[con].l=order;
            ji[con].r=i;
        }
        q[a[i]]=i;
    }

    for(int i=1;i<=con;++i)
    {
        L[ji[i].l].push_back(ji[i].r);
        R[ji[i].r].push_back(ji[i].l);
    }
}

ll work()
{
    ll ans=0;
    int tt,mx,mn;
    mx=0;
    for(int i=1;i<=n;++i)
    {
        tt=R[i].size();
        for(int j=0;j<tt;++j)
            if(mx<R[i][j])
                mx=R[i][j];
        ans+=(i-mx);
    }
    /*mn=n+1;
    for(int i=n;i>=1;--i)
    {
        tt=L[i].size();
        for(int j=0;j<tt;++j)
            if(mn>L[i][j])
                mn=L[i][j];
        ans+=(mn-i);
    }
    return ans/2;*/
    return ans;
}

int main(){

    //freopen("T2.in","r",stdin);
    //freopen("T2.out","w",stdout);

    n=read();K=read();
    for(int i=1;i<=n;++i)
    {
        a[i]=read();
        if(maxa<a[i])
            maxa=a[i];
    }
    chu();
    cout<<work();
}
T2

 

T3

$f_{i,j}$ 前i行 第i行用恰好j种颜色的方案数

$$ f_{i,j}=(\sum_{k=1}^{a_{i-1}}f_{i-1,k})*C_m^j*g_{a_i,j} - f_{i-1,j}*g_{a_i,j} $$

其中 g_{i,j} 表示 在i个位置里用j种颜色放的方案数

$$g_{i,j}=g_{i-1,j}*(j-1)+g_{i-1,j-1}*j$$

 

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <map>
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
inline int read()
{
    char q=getchar();int ans=0;
    while(q<'0'||q>'9')q=getchar();
    while(q>='0'&&q<='9'){ans=ans*10+q-'0';q=getchar();}
    return ans;
}
const int N=1000006;

int prime[N],cnt;
bool he[N];
int mn[N];

int n,m,mod;
int a[N],maxa;

ll g[5006][5006];
ll C[N];

void get_g()
{
    g[1][1]=1;//没有组合意义 
    for(int i=1;i<=maxa;++i)
        for(int j=1;j<=i&&j<=m;++j)
        {
            g[i][j]=(g[i][j]+g[i-1][j]*(j-1)%mod)%mod;
            g[i][j]=(g[i][j]+g[i-1][j-1]*j%mod)%mod;
        }
    /*printf("\n");
    for(int i=1;i<=maxa;++i)
    {
        for(int j=1;j<=maxa;++j)
            printf("%lld ",g[i][j]);
        printf("\n");
    }
    printf("\n");*/
}

int t[N];

inline void jia(int x)
{
    while(x!=1)
    {
        ++t[mn[x]];
        x/=prime[mn[x]];
    }
}

inline void jian(int x)
{
    while(x!=1)
    {
        --t[mn[x]];
        x/=prime[mn[x]];
    }
}

inline ll get_get()
{
    ll ans=1;
    for(int i=1;i<=cnt;++i)
        if(t[i])
            for(int j=1;j<=t[i];++j)
              ans=ans*prime[i]%mod;
    return ans;
}

void chu()
{
    int q1=min(maxa,m);
    
    for(int i=2;i<=m;++i)
    {
        if(!he[i])
        {
            prime[++cnt]=i;
            mn[i]=cnt;
        }
        for(int j=1;j<=cnt&&prime[j]*i<=m;++j)
        {
            he[i*prime[j]]=1;
            mn[i*prime[j]]=j;
            if(i%prime[j]==0)
                break;
        }
    }
    
    for(int i=0;i<q1;++i)
    {
        jia(m-i);
        jian(i+1);
        C[i+1]=get_get();
        //printf("%lld ",C[i+1]);
    }
    //printf("\n");
}

ll f[2][1000006];

ll dp()
{
    int pre;
    int now=0;
    f[0][0]=1;
    for(int i=1;i<=n;++i)
    {
        now^=1;pre=now^1;
        for(int j=0;j<=maxa;++j)
            f[now][j]=0;
        //printf("now=%d pre=%d\n",now,pre);
        for(int j=1;j<=a[i];++j)
          f[now][j]=(f[pre][0]*C[j]%mod*g[a[i]][j]%mod-f[pre][j]*g[a[i]][j]%mod+mod)%mod;
        f[now][0]=0;
        for(int j=1;j<=a[i];++j)
            f[now][0]=(f[now][0]+f[now][j])%mod;
    }
    return f[now][0]%mod;
}

int main(){

    //freopen("T3.in","r",stdin);
    //freopen("kalanchoe6.in","r",stdin);

    n=read();m=read();mod=read();
    for(int i=1;i<=n;++i)
    {
        a[i]=read();
        if(maxa<a[i])
            maxa=a[i];
    }
    get_g();
    chu();
    cout<<dp();
}
T3

 

今天真是日了狗了...

第一题,想了半天以为是正解,其实是又犯了老错误

每一个简单题,我都要把它搞复杂,以后要先把原始式子写出来...

而且想到的东西要及时写下来,防止像今天第三题忘了...

以后有价值的题在写blog,太浪费时间了...

posted @ 2017-10-14 19:35  A_LEAF  阅读(183)  评论(0编辑  收藏  举报