CQOI2018day1 (XJOI contest908)

一题

破解D-H协议

 

时间限制:1S

内存限制:512M

具体思路:BSGS,没了

AC代码

#include<bits/stdc++.h>
using namespace std;
#define int long long

int n,i,j,p,g,a,b,A,B;
map<int,pair<int,int> > mp;
int qpow(int a,int b)
{
    int ans=1;
    while(b)
    {
        if(b%2)ans=ans*a%p;
        b=b/2;a=a*a%p;
    }
    return ans;
}
main()
{
//    freopen("A.in","r",stdin);
//    freopen("A.out","w",stdout);
    scanf("%lld%lld",&g,&p);
    scanf("%lld",&n);
    int m=100000;
    for(i=0;i<=m;i++)mp[qpow(g,i)]=make_pair(1,i);
    while(n--)
    {
        scanf("%lld%lld",&a,&b);
        for(i=0;i<=m;i++)
        {
            int now=i*m;
            if(mp[qpow(qpow(g,now),p-2)*a%p].first)
            {
                A=now+mp[qpow(qpow(g,now),p-2)*a%p].second;
                break;
            }
        }
        for(i=0;i<=m;i++)
        {
            int now=i*m;
            if(mp[qpow(qpow(g,now),p-2)*b%p].first)
            {
                B=now+mp[qpow(qpow(g,now),p-2)*b%p].second;
                break;
            }
        }
        
        printf("%lld
",qpow(qpow(g,B),A)%p);
    }
    
    return 0;
}

第二题

社交网络

时间限制:1S

内存限制:512M

具体思路:矩阵树定理

先搞出基尔霍夫矩阵,然后去掉第一行列,然后高斯消元求行列式即可

AC代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,i,j,a[500000],b[500000],k;
int f[300][300];
const int ha=10007;
int qpow(int a,int b)
{
    int ans=1;
    while(b)
    {
        if(b%2)ans=ans*a%ha;
        b=b/2;a=a*a%ha;
    }
    return ans;
}
int gauss()
{
    int ans=0;
    for(i=1;i<=n;i++)
    {
        int mx=i;
        for(j=i+1;j<=n;j++)if(f[j][i]>f[mx][i])mx=j;
        if(mx!=i)
        {
            ans^=1;
            for(j=1;j<=n;j++)
            swap(f[i][j],f[mx][j]);
        }
        if(f[i][i]==0)
        {
            f[1][1]=0;
            return 0;
        }
        
        for (j=i+1;j<=n;j++)
        if(f[j][i]!=0)
        {
            int now=f[j][i]*qpow(f[i][i],ha-2)%ha;
            for (k=i;k<=n;k++)f[j][k]=(f[j][k]-now*f[i][k]%ha+ha*ha)%ha;
        }
    }
    return ans;
}
main()
{
    scanf("%lld%lld",&n,&m);
    for(i=1;i<=m;i++)
    {
        scanf("%lld%lld",&a[i],&b[i]);
        if(a[i]==1)a[i]=n;else if(a[i]==n)a[i]=1;
        if(b[i]==n)b[i]=1;else if(b[i]==1)b[i]=n;
            
        f[a[i]][b[i]]-=1;f[a[i]][b[i]]=(f[a[i]][b[i]]+ha)%ha;
        f[a[i]][a[i]]+=1;f[a[i]][a[i]]=(f[a[i]][a[i]]+ha)%ha;
    }
    n--;
    int ans=gauss()?(ha-1):1;
    for(i=1;i<=n;i++)ans=ans*f[i][i]%ha;
    printf("%lld",ans);
    return 0;
}

第三题

交错序列

 

时间限制:1S

内存限制:512M

具体思路:O(n)枚举,然后组合数乱搞就过了

AC代码

#pragma GCC optimize(3)
#pragma GCC target("avx")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include<bits/stdc++.h>
using namespace std;
#define int long long
int tot,n,m,i,j,A[10001000], B[10001000],inv[10000010],factinv[10000010],fact[10000010],pri[1001000],mod;
bool np[10001000];
int a,b,ans;
int qpow(int a,int b)
{
    int ans=1;
    while(b)
    {
        if(b%2)ans=ans*a%mod;
        b=b/2;
        a=a*a%mod;
    }
    return ans;
}
int C(int x,int y)
{
    return fact[x]*factinv[y]%mod*factinv[x-y]%mod;
}
main()
{
    scanf("%lld%lld%lld%lld",&n,&a,&b,&mod);
    m=min(n+1,mod-1);
    inv[1]=1;factinv[1]=1;fact[1]=1;inv[0]=1;
    for(i=2; i<=m; i++)fact[i]=fact[i-1]*i%mod;
    factinv[m]=qpow(fact[m],mod-2); 
    for (i=m;i>0;--i) factinv[i-1]=factinv[i]*i%mod;
    A[0]=!a;B[0]=!b;A[1]=B[1]=1;
    for (i=2; i<=n; ++i)
    {
        if (!np[i])
        {
            A[i]=qpow(i,a);
            B[i]=qpow(i,b);
            pri[++tot]=i;
        }
        for (j=1; j<=tot&&pri[j]*i<=n; ++j)
        {
            np[pri[j]*i]=1;
            A[pri[j]*i]=A[i]*A[pri[j]]%mod;
            B[pri[j]*i]=B[i]*B[pri[j]]%mod;
            if (i%pri[j]==0) break;
        }
    }
    for(i=0; i<=(n+1)/2; i++)
    ans+=C(n-i+1,i) *A[n-i]%mod *B[i]%mod;
    printf("%lld",ans%mod);
    return 0;
}
原文地址:https://www.cnblogs.com/Orange-User/p/8916679.html