省队集训Round3 DAY5

T1

这里写图片描述

题解

考试的时候考虑了两种方法,但是无法处理n%3=1的部分情况。
首先n%4==3或n%4==0都可以填成一个两个行的矩阵,先填好前四个,然后四个一循环
这里写图片描述
如果n%3==2或n%3==0,那么先填好前三个,然后三个一循环。
这里写图片描述
剩下的怎么办呢?
先把前三个填好,然后剩下的两两一组,每次增加两列一行。
这里写图片描述
如果最后是偶数,那么直接增加两列就可以了。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>+
#include<cmath>
using namespace std;
int a[3][1000000],b[4][1000000],n,c[2003][2003];
int main()
{
    freopen("deep.in","r",stdin);
    freopen("deep.out","w",stdout);
    scanf("%d",&n);
    if (n==1) {
        printf("1 1\n");
        printf("1\n");
        return 0;
    }
    if (n==2) {
        printf("1 3\n");
        printf("1 2 2\n");
        return 0;
    }
    if (n==3) {
        printf("3 2\n");
        printf("3 3\n");
        printf("3 1\n");
        printf("2 2\n");
        return 0;
    }
    if (n%4==3||n%4==0) {
        a[1][1]=a[2][1]=a[2][2]=3;
        a[1][2]=1;
        a[1][3]=a[2][3]=a[1][4]=a[1][5]=4;
        a[2][4]=a[2][5]=2;
        int cnt=5; 
        for (int i=5;i<=n;i++){
            if (i%4==1) {
                int t=i/2;
                for (int j=1;j<=t;j++) a[1][++cnt]=a[2][cnt]=i;
                a[1][++cnt]=i;
            }
            if (i%4==2) {
                a[2][cnt]=i;
                int t=i/2-1;
                for (int j=1;j<=t;j++) a[1][++cnt]=a[2][cnt]=i;
                a[1][++cnt]=i;
            }
            if (i%4==3) {
                a[2][cnt]=i;
                int t=i/2;
                for (int j=1;j<=t;j++) a[1][++cnt]=a[2][cnt]=i;
            }
            if (i%4==0) {
                int t=i/2;
                for (int j=1;j<=t;j++) a[1][++cnt]=a[2][cnt]=i;
            }
        }
        printf("2 %d\n",cnt);
        for (int i=1;i<=2;i++,printf("\n"))
         for (int j=1;j<=cnt;j++) printf("%d ",a[i][j]);
        return 0;
    }
    if (n%3==2||n%3==0){
        b[1][1]=b[1][2]=b[2][1]=3;
        b[2][2]=1;
        b[3][1]=b[3][2]=2;
        int cnt=2;
        for (int i=4;i<=n;i++){
            if (i%3==1) {
                int t=i/3;
                for (int j=1;j<=t;j++) b[1][++cnt]=b[2][cnt]=b[3][cnt]=i;
                b[1][++cnt]=i;
            }
            if (i%3==2) {
                int t=i/3;
                b[2][cnt]=b[3][cnt]=i;
                for (int j=1;j<=t;j++) b[1][++cnt]=b[2][cnt]=b[3][cnt]=i;
            }
            if (i%3==0) {
                int t=i/3;
                for (int j=1;j<=t;j++) b[1][++cnt]=b[2][cnt]=b[3][cnt]=i; 
            }
        }
        printf("3 %d\n",cnt);
        for (int i=1;i<=3;i++,printf("\n"))
         for (int j=1;j<=cnt;j++) printf("%d ",b[i][j]);
        return 0;
    }
    c[1][1]=1;
    c[2][1]=c[2][2]=2;
    c[1][2]=c[2][3]=c[1][3]=3;
    int h=2; int l=3; int i;
    bool pd=false;
    if (n%2==0) pd=true,n--;
    for (i=4;i<=n;i+=2) {
        ++h;
        for (int j=1;j<=l+1;j++) c[h][j]=i+1;
        int t=h-1-(i-l)+1;
        for (int j=h-1;j>=t;j--) c[j][l+1]=i+1;
        for (int j=1;j<=t-1;j++) c[j][l+1]=i;
        for (int j=1;j<=h;j++) c[j][l+2]=i;
        l+=2;
    }
    if (pd){
      for (int j=1;j<=h;j++) c[j][l+1]=c[j][l+2]=n+1;
      l+=2;
    }
    printf("%d %d\n",h,l);
    for (int i=1;i<=h;i++,printf("\n"))
     for (int j=1;j<=l;j++) printf("%d ",c[i][j]);
}

T2

这里写图片描述

题解

注意题意是求出完美无向图的个数x,然后输出 mx
那么关键就是怎么求x.

x=k|nC(n,k)C(nk,k)..C(k,k)

x=k|nn!(k!)nk(nk)!

注意x的模数是 ϕ(p) ,对 ϕ(p) 进行质因数分解,然后用类似扩展lucas定理的方式求解上面的式子,最后用中国剩余定理合并即可。

代码

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define LL long long
#define mod 999999599 
#define pa pair<int,int>
using namespace std;
int n,m,M[5],ans[5];
int quickpow(int num,int x,int p)
{
    int ans=1,base=num%p;
    while (x) {
        if (x&1) ans=ans*base%p;
        x>>=1;
        base=base*base%p;
    }
    return ans;
}
pa solve(int n,int p)
{
    if (n==0) return make_pair(0,1);
    int x=n/p,y=n/p;
    int ans=1;
    if (y) {
        for (int i=2;i<p;i++)
         if (i%p!=0) ans=(LL)ans*i%p;
        ans=quickpow(ans,y,p);
    }
    for (int i=y*p+1;i<=n;i++)
     if (i%p!=0) ans=(LL)ans*i%p;
    pa t=solve(x,p);
    return make_pair(t.first+x,(LL)ans*t.second%p);
}
int calc(int n,int k,int p)
{
    pa a=solve(n,p);
    pa b=solve(n/k,p);
    pa c=solve(k,p);
    int t1=quickpow(p,a.first-b.first-(n/k)*c.first,p)*a.second%p;
    t1=t1*quickpow(b.second,p-2,p)%p;
    t1=t1*quickpow(quickpow(c.second,p-2,p),n/k,p)%p;
    return t1;
}
int solve(int p)
{
    int ans=0;
    for (int i=1;i*i<=n;i++)
     if (n%i==0) {
        ans+=calc(n,i,p);
        if (i*i!=n) ans+=calc(n,n/i,p);
        ans%=p;
     }
    return ans;
}
int china()
{
    LL ans1=0;
    for (int i=1;i<=4;i++){
        int M1=(mod-1)/M[i];
        //cout<<M1<<" "<<quickpow(M1,M[i]-2,M[i])<<" "<<ans[i]<<endl;
        ans1=(ans1+(LL)quickpow(M1,M[i]-2,M[i])*(LL)M1*(LL)ans[i]%(mod-1))%(mod-1);
    }
    //cout<<ans1<<endl;
    return ans1%(mod-1);
}
LL quickpow2(int num,int x,LL p)
{
    LL ans=1,base=num%p;
    while (x) {
        if (x&1) ans=ans*base%p;
        x>>=1;
        base=base*base%p;
    }
    return ans;
}
int main()
{
    freopen("dark.in","r",stdin);
    freopen("dark.out","w",stdout);
    scanf("%d%d",&n,&m);
    M[1]=2; M[2]=13; M[3]=5281; M[4]=7283;
    for (int i=1;i<=4;i++)
     ans[i]=solve(M[i]);
    printf("%d\n",(int)quickpow2(m,china(),mod));
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值