Contest - ACdream原创群赛の妹子的假期生活 解题报告

总体情况:

昨天做的人不是很多啊T_T , 以下是Board

Contest - ACdream原创群赛の妹子的假期生活 解题报告_第1张图片

感谢帮我验题的同学们:

Contest - ACdream原创群赛の妹子的假期生活 解题报告_第2张图片

本来想是覆盖所有知识点的,失败T_T ,木有出字符串,搜索也是图论过的T_T

P.S. 

本次解题报告代码要和http://blog.csdn.net/dslovemz/article/details/8435024 配套使用

A 孟竹的Triple

Dynamic Programming
仿照本次长春赛区H题出的一个题目。
状态是 dp[数个数][和][LCM][异或值]。不过这样肯定是要MLE+TLE的。于是两种优化:
1、数的个数,因为递推的时候只会从 i -> i + 1于是用滚动数组
2、LCM , 预处理1~100所有数字的约数,以及两个约数LCM
typedef long long int64;

struct Int {
	int x;
	Int() :
			x(0) {
	}
	Int(int _x) :
			x(_x) {
		x %= MOD;
		if (x < 0)
			x += MOD;
	}
	Int(int64 _x) {
		x = _x % MOD;
		if (x < 0)
			x += MOD;
	}
	static Int get(int x) {
		Int a;
		a.x = x;
		return a;
	}

	Int operator+(const Int&o) const {
		int t = x + o.x;
		if (t >= MOD)
			t -= MOD;
		return get(t);
	}
	Int operator*(const Int&o) const {
		return get(1LL * x * o.x % MOD);
	}
	Int operator-(const Int&o) const {
		int t = x - o.x;
		if (t < 0)
			t += MOD;
		return get(t);
	}
	Int operator/(const Int&o) const {
		return (*this) * o.inv();
	}
	Int&operator+=(const Int&o) {
		return (*this) = *this + o;
	}
	Int&operator-=(const Int&o) {
		return (*this) = *this - o;
	}
	Int&operator*=(const Int&o) {
		return (*this) = *this * o;
	}
	Int&operator/=(const Int&o) {
		return (*this) = *this / o;
	}

	Int power(int64 n) const {
		if (!n)
			return get(1);
		const Int&a = *this;
		if (n & 1)
			return power(n - 1) * a;
		else
			return (a * a).power(n >> 1);
	}

	Int inv() const {
		return power(MOD - 2);
	}
};
/* .................................................................................................................................. */
Int dp[2][102][15][139];
VI Factor[101];
int FactorP[101][101] , lcmP[101][101][101] , FactorCnt[101];
int n , a , b , c;
void init(){
    for (int i = 0 ; i <= 100 ; ++i)
        Factor[i].clear();
    RST(FactorP);
    RST(lcmP);
    for (int i = 1 ; i <= 100 ; ++i){
        for (int j = 1 ; j <= i ; ++j)
            if (i % j == 0){
                Factor[i].PB(j);
                FactorP[i][j] = SZ(Factor[i]) - 1;
            }
        FactorCnt[i] = SZ(Factor[i]);
    }
    for (int i = 1 ; i <= 100 ; ++i){
        for (int j = 0 ; j < FactorCnt[i] ; ++j)
        for (int k = 0 ; k < FactorCnt[i] ; ++k){
            int p = Factor[i][j];
            int q = Factor[i][k];
            int r = p / GCD(p , q) * q;
            r = FactorP[i][r];
            lcmP[i][j][k] = r;
        }
    }
}
void solve(){
    RD(n , a , b , c);
    RST(dp);
    dp[0][0][0][0].x = 1;
    for (int i = 0 ; i < n ; ++i){
        int nw = i & 1;
        int nx = 1 - nw;
        for (int sum = 0 ; sum <= a ; ++sum)
        for (int lcmnow = 0 ; lcmnow < FactorCnt[b] ; ++lcmnow)
        for (int xorsum = 0 ; xorsum <= 128 ; ++xorsum)
            dp[nx][sum][lcmnow][xorsum].x = 0;
        for (int sum = 0 ; sum <= a ; ++sum)
        for (int lcmnow = 0 ; lcmnow < FactorCnt[b] ; ++lcmnow)
        for (int xorsum = 0 ; xorsum < 128 ; ++xorsum){
//                printf("dp[%d][%d][%d][%d] = %d\n" , nw , sum , lcmnow , xorsum , dp[nw][sum][lcmnow][xorsum]);
            if (dp[nw][sum][lcmnow][xorsum].x == 0) continue;
            for (int add = 0 ; add < FactorCnt[b] && Factor[b][add] + sum <= a; ++add){
                int addFactor = Factor[b][add];
//                printf("ADD dp[%d][%d][%d][%d] += %d\n" , nx , sum + addFactor , lcmP[b][lcmnow][add] , (xorsum ^ addFactor) , dp[nw][sum][lcmnow][xorsum].x);
                dp[nx][sum + addFactor][lcmP[b][lcmnow][add]][(xorsum ^ addFactor)] += dp[nw][sum][lcmnow][xorsum];
            }
        }
    }
    printf("%d\n" , dp[(n & 1)][a][FactorP[b][b]][c].x);
//    if (dp[(n & 1)][a][FactorP[b][b]][c].x) printf("%d %d %d %d\n" , n , a , b , c);
}
int main(){
    freopen("0.in" , "r" , stdin);
    freopen("0.out" , "w" , stdout);
    init();
    Rush solve();
}

B 孟竹的复习计划

动态求逆序对,树状数组 / 线段树。
这题其实是有一次我做CF的时候看错题了,突然想到的T_T
方法是开100棵树状数组,每次询问花100 * logn的时间,所以复杂度就是(n + m)*100 * logn

SEGMENT - TREE

#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
const int maxn = 10009;
struct TREE{
    int tree[maxn<<2];
    void PushUP(int rt) {
        tree[rt] = (tree[rt<<1] + tree[rt<<1|1]);
    }
    void build(int l,int r,int rt) {
        if (l == r) {
            //scanf("%d",&tree[rt]);
            tree[rt] = 0;
            return ;
        }
        int m = (l + r) >> 1;
        build(lson);
        build(rson);
        PushUP(rt);
    }
    void update(int p,int sc,int l,int r,int rt) {
        if (l == r) {
            tree[rt] = sc;
            return ;
        }
        int m = (l + r) >> 1;
        if (p <= m) update(p , sc , lson);
        else update(p , sc , rson);
        PushUP(rt);
    }
    int query(int L,int R,int l,int r,int rt) {
        if (L <= l && r <= R) {
            return tree[rt];
        }
        int m = (l + r) >> 1;
        int ret = 0;
        if (L <= m) {
            int res= query(L , R , lson);
            ret += (res);
        }
        if (R > m) {
           int res= query(L , R , rson);
           ret += (res);
        }
        return ret;
    }
}tree[109];
int a[maxn] , n , m;
struct IO{
    int op , x , y;
    void input(){
        RD(op , x , y);
    }
}io[10009];
VI hashT;
VI edge[109];
MII hash;
int L;
int cal(int po , int val){
    int res = 0;
    for (int i = 1 ; i <= L ; ++i){
        if (i < val && po < n)
            res += tree[i].query(po + 1 , n , 1 , n , 1);
        if (i > val && po > 1)
            res += tree[i].query(1 , po - 1 , 1 , n , 1);
    }
    return res;
}
void changeNumber(int po , int val){
    tree[a[po]].update(po , 0 , 1 , n , 1);
    tree[val].update(po , 1 , 1 , n , 1);
}
void solve(){
    RD(n , m);
    hash.clear();
    hashT.clear();
    for (int i = 1 ; i <= n ; ++i) RD(a[i]) , hashT.PB(a[i]);
    for (int i = 1 ; i <= m ; ++i){
        io[i].input();
        if (io[i].op == 0) hashT.PB(io[i].y);
    }
    sort(ALL(hashT));
    L = unique(ALL(hashT)) - hashT.begin();
    for (int i = 0 ; i < L ; ++i)
        hash[hashT[i]] = i + 1 ;
    for (int i = 1 ; i <= n ; ++i) a[i] = hash[a[i]];
    for (int i = 1 ; i <= m ; ++i)
        if (io[i].op == 0)
            io[i].y = hash[io[i].y];
    for (int i = 0 ; i <= L ; ++i){
        tree[i].build(1 , n , 1);
        edge[i].clear();
    }

    for (int i = 1 ; i <= n ; ++i){
        edge[a[i]].PB(i);
    }

    int ans = 0;
    for (int i = 1 ; i <= L ; ++i){
        for (int j = 0 ; j < SZ(edge[i]) ; ++j){
            int now = edge[i][j];
            if (now < n) ans += tree[0].query(now + 1 , n , 1 , n , 1);
        }
        for (int j = 0 ; j < SZ(edge[i]) ; ++j){
            int now = edge[i][j];
            tree[0].update(now , 1 , 1 , n , 1);
        }
    }
    tree[0].build(1 , n , 1);
    for (int i = 1 ; i <= n ; ++i)
        tree[a[i]].update(i , 1 , 1 , n , 1);
    printf("%d\n" , ans);
    for (int cas = 1 ; cas <= m ; ++cas){
        int op = io[cas].op , x = io[cas].x , y = io[cas].y;
        int change = 0;
        if (op == 0){
            change -= cal(x , a[x]);
            change += cal(x , y);
            ans += change;
            changeNumber(x , y);
            a[x] = y;
        }
        else{
            if (x > y) swap(x , y);
            change -= cal(x , a[x]);
            change -= cal(y , a[y]);
            changeNumber(x , a[y]);
            changeNumber(y , a[x]);
            swap(a[x] , a[y]);
            change += cal(x , a[x]);
            change += cal(y , a[y]);
            if (a[x] > a[y]) change--;
            else if (a[x] < a[y]) change++;
            ans += change;
        }
        printf("%d\n" , ans);
    }
}
int main(){
//    freopen("0.in" , "r" , stdin);
//    freopen("segmengtree.out" , "w" , stdout);
    Rush solve();
}

BIT

const int maxn = 10009;
int n;
struct TREE{
    int tree[maxn] , cnt;
    void init(){
        RST(tree);
        cnt = 0;
    }
    void add(int po , int c){
        for ( ; po< maxn ; po += low_bit(po))
            tree[po] += c;
        cnt += c;
    }
    int query(int po){
        int ret = 0;
        for (; po > 0 ; po -= low_bit(po))
            ret += tree[po];
        return ret;
    }
}tree[109];
int a[maxn] , m;
struct IO{
    int op , x , y;
    void input(){
        RD(op , x , y);
    }
}io[10009];
VI hashT;
VI edge[109];
MII hash;
int L;
int cal(int po , int val){
    int res = 0;
    for (int i = 1 ; i <= L ; ++i){
        if (i < val && po < n)
            res += tree[i].cnt - tree[i].query(po - 1);
        if (i > val && po > 1)
            res += tree[i].query(po - 1);
    }
    return res;
}
void changeNumber(int po , int val){
    tree[a[po]].add(po , -1);
    tree[val].add(po , 1);
}
void solve(){
    RD(n , m);
    hash.clear();
    hashT.clear();
    for (int i = 1 ; i <= n ; ++i) RD(a[i]) , hashT.PB(a[i]);
    for (int i = 1 ; i <= m ; ++i){
        io[i].input();
        if (io[i].op == 0) hashT.PB(io[i].y);
    }
    sort(ALL(hashT));
    L = unique(ALL(hashT)) - hashT.begin();
    for (int i = 0 ; i < L ; ++i)
        hash[hashT[i]] = i + 1 ;
    for (int i = 1 ; i <= n ; ++i) a[i] = hash[a[i]];
    for (int i = 1 ; i <= m ; ++i)
        if (io[i].op == 0)
            io[i].y = hash[io[i].y];
    for (int i = 0 ; i <= L ; ++i){
        tree[i].init();
        edge[i].clear();
    }

    for (int i = 1 ; i <= n ; ++i){
        edge[a[i]].PB(i);
    }

    int ans = 0;
    for (int i = L ; i >= 1 ; --i){
        for (int j = 0 ; j < SZ(edge[i]) ; ++j){
            int now = edge[i][j];
            ans += tree[0].query(now);
        }
        for (int j = 0 ; j < SZ(edge[i]) ; ++j){
            int now = edge[i][j];
            tree[0].add(now , 1);
        }
    }
    tree[0].init();
    for (int i = 1 ; i <= n ; ++i)
        tree[a[i]].add(i , 1);
    printf("%d\n" , ans);
    for (int cas = 1 ; cas <= m ; ++cas){
        int op = io[cas].op , x = io[cas].x , y = io[cas].y;
        int change = 0;
        if (op == 0){
            change -= cal(x , a[x]);
            changeNumber(x , y);
            change += cal(x , y);
            ans += change;
            a[x] = y;
        }
        else{
            if (x > y) swap(x , y);
            change -= cal(x , a[x]);
            change -= cal(y , a[y]);
            changeNumber(x , a[y]);
            changeNumber(y , a[x]);
            swap(a[x] , a[y]);
            change += cal(x , a[x]);
            change += cal(y , a[y]);
            if (a[x] > a[y]) change--;
            else if (a[x] < a[y]) change++;
            ans += change;
        }
        printf("%d\n" , ans);
    }
}
int main(){
//    freopen("0.in" , "r" , stdin);
//    freopen("bit.out" , "w" , stdout);
    Rush solve();
}

XLK 的 二维BIT

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<vector>
using namespace std;
#define fr(i,n) for(int i=0;i<n;i++)
#define fo(i,n) for(int i=1;i<=n;i++)
#define fe(i,n) for(__typeof(n.begin()) i=n.begin();i!=n.end();i++)
int c[105][10020];
int a[10020];
int n,m,z,t;
int R(int x,int y,int z)
{
    for(int i=x;i<=100;i+=i&-i)
        for(int j=y;j<=n;j+=j&-j)
            c[i][j]+=z;
}
int G(int x,int y)
{
    int _=0;
    for(int i=x;i;i-=i&-i)
        for(int j=y;j;j-=j&-j)
            _+=c[i][j];
    return _;
}
void C(int p,int x)
{
    R(a[p],p,-1);
    z-=G(100,p)-G(a[p],p);
    z-=G(a[p]-1,n)-G(a[p]-1,p);
    a[p]=x;
    R(a[p],p,+1);
    z+=G(100,p)-G(a[p],p);
    z+=G(a[p]-1,n)-G(a[p]-1,p);
}
int main()
{
    for(scanf("%d",&t);t--;)
    {
        z=0;
        memset(c,0,sizeof c);
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",a+i);
            z+=G(100,i)-G(a[i],i);
            R(a[i],i,1);
        }
        printf("%d\n",z);
        for(int i=0;i<m;i++)
        {
            int o,x,y;
            scanf("%d%d%d",&o,&x,&y);
            if(o==1)
            {
                int ax=a[x],ay=a[y];
                C(x,ay);
                C(y,ax);
            }
            else
            {
                C(x,y);
            }
            printf("%d\n",z);
        }
    }
}


C 孟竹的幼儿园生活

简单计算几何。
分成两部分:
1、给正方形对角线,求四个角——模板
2、HPI , nlogn半平面交

XLK 的代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<math.h>
const double inf=1e8;
const double eps=1e-8;
const double pi=acos(-1.);
using namespace std;
struct P
{
    double x,y;
    P(){}
    P(double x,double y):x(x),y(y){}
    void scan()
    {
        scanf("%lf %lf",&x,&y);
    }
    void print(string s="")
    {
        if(s!="")
            cout << s << ": ";
        printf("%.2f %.2f\n",x,y);
    }
    double dis(const P&a)
    {
        return hypot(x-a.x,y-a.y);
    }
    P rot(double f)
    {
        double sf=sin(f),cf=cos(f);
        return P(x*cf-y*sf,y*cf+x*sf);
    }
    double dot(const P&a)
    {
        return x*a.x+y*a.y;
    }
    double det(const P&a)
    {
        return x*a.y-y*a.x;
    }
}p[4020],s[4020],o;
    bool operator==(const P&a,const P&b)
    {
        return fabs(a.x-b.x)<eps&&fabs(a.y-b.y)<eps;
    }
    bool operator!=(const P&a,const P&b)
    {
        return !(a==b);
    }
    bool operator<(const P&a,const P&b)
    {
        if(fabs(a.x-b.x)<eps)
            return a.y<b.y;
        return a.x<b.x;
    }
    P operator+(const P&a,const P&b)
    {
        return P(a.x+b.x,a.y+b.y);
    }
    P operator-(const P&a,const P&b)
    {
        return P(a.x-b.x,a.y-b.y);
    }
    P operator/(const P&a,double f)
    {
        return P(a.x/f,a.y/f);
    }
    P operator*(const P&a,double f)
    {
        return P(a.x*f,a.y*f);
    }
int pc,sc;
double r;
int sgn(double x)
{
    return (x>eps)-(x<-eps);
}
double xm(P a,P b,P c)
{
    return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);
}
P cp(P as,P ae,P bs,P be)
{
    P re;
    double u=xm(as,ae,bs);
    double v=xm(ae,as,be);
    re.x=(bs.x*v+be.x*u)/(u+v);
    re.y=(bs.y*v+be.y*u)/(u+v);
    return re;
}
void ins(P a,P b)
{
    int i;
    sc=0;
    for(i=1;i<pc;i++)
    {
        if(sgn(xm(a,b,p[i]))>=0)
            s[++sc]=p[i];
        if(sgn(xm(a,b,p[i])*xm(a,b,p[i+1]))<0)
            s[++sc]=cp(a,b,p[i],p[i+1]);
    }
    pc=sc;
    if(sc==0)
        return;
    memcpy(p,s,sizeof(p));
    p[++pc]=p[1];
    return;
}
void mov(P a,P b,P&c,P&d)
{
    P o=P(a.y-b.y,b.x-a.x);
    double l=sqrt(o.x*o.x+o.y*o.y);
    o.x=o.x/l*r;
    o.y=o.y/l*r;
    c.x=a.x+o.x;
    c.y=a.y+o.y;
    d.x=b.x+o.x;
    d.y=b.y+o.y;
    return;
}
double dis(P a,P b)
{
    return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
double S(P p[],int n)
{
    double re=0;
    int i;
    for(i=1;i<n;i++)
        re+=xm(o,p[i],p[i+1]);
    return fabs(re/2);
}
int main()
{
    int t;
    for(scanf("%d",&t);t--;)
    {
        int n,i,j,ans1,ans2;
        double ans=0,ds;
        scanf("%d",&n);
        p[1]=P(-10000,-10000);
        p[2]=P(10000,-10000);
        p[3]=P(10000,10000);
        p[4]=P(-10000,10000);
        p[pc=5]=p[1];
        for(i=1;i<=n;i++)
        {
            P u,v,o,p,q;
            u.scan();
            v.scan();
            o=(u+v)/2;
            p=(u-o).rot(pi/2)+o;
            q=(v-o).rot(pi/2)+o;
            ins(u,p);
            ins(p,v);
            ins(v,q);
            ins(q,u);
        }
        printf("%.4f\n",S(p,pc));
    }
    return 0;
}



孟竹跪DP

也是一个CF的原题。方法是枚举每个数字,记录左边离这个数字最近的二进制第i位是0或者1的数字的位置,暴力优化。复杂度O(n)

bool ans[2000000];
int MI[31];
void init(){
    for (int i = 0 ; i <= 29 ; ++i)
        MI[i] = 1 << i;
}
int n;
struct Meng{
    int t , po;
    bool operator < (const Meng & A) const{
        if (po != A.po) return po > A.po;
        return t < A.t;
    }
}dp0[31] , dp1[31];
const int ALL = (1 << 21) - 1;
bool cmp(Meng A , Meng B){
    return A.t < B.t;
}
#define LIMIT 21
int po0[LIMIT + 1] , po1[LIMIT + 1];
void solve(){
    RD(n);
    RST(ans);
//cout << ALL << endl;
    for (int i = 0 ; i < LIMIT ; ++i){
        dp0[i].t = i , dp1[i].t = i;
        dp0[i].po = -1 , dp1[i].po = -1;
    }
    for (int i = 0 ; i < n ; ++i){
        int x , y , z;
        RD(x);y = x , z = x;
        ans[x] = 1;
        for (int j = 0 ; j < LIMIT ; ++j){
            po0[dp0[j].t] = j;
            po1[dp1[j].t] = j;
        }
        for (int j = 0 ; j < LIMIT ; ++j){
            if(x & 1) dp1[po1[j]].po = i;
            else dp0[po0[j]].po = i;
            x >>= 1;
        }
        sort(dp0 , dp0 + LIMIT);
        sort(dp1 , dp1 + LIMIT);
//cout << i << endl;
        for(int j = 0 ; j < LIMIT ; ++j){
            if (dp0[j].po != -1){
//cout << "0"<<j<<endl;
//cout << dp0[j].t<<endl;
                y &= (ALL ^ MI[dp0[j].t]);
                if (j == LIMIT - 1 || dp0[j].po != dp0[j + 1].po){
//cout << y << endl;
                    ans[y] = 1;
                }
            }
            if (dp1[j].po != -1){
//cout << "1"<<j<<endl;
                z |= MI[dp1[j].t];
                if (j == LIMIT - 1 || dp1[j].po != dp1[j + 1].po){
//cout << z << endl;
                    ans[z] = 1;
                }
            }
        }
    }
//cout << "DS" << endl;
    int ANS = 0;
    for (int i = 0 ; i < 2000000 ; ++i)
        if (ans[i]) {
//cout << i << endl;
                ++ANS;
        }
    printf("%d\n" , ANS);
}
int main(){
    freopen("0.in" , "r" , stdin);
    freopen("0.out" , "w" , stdout);
    init();
    Rush solve();
}





E 孟竹和屌丝玩儿游戏

双指针+数据结构
首先,如果要求和不大于K的话,双指针就可以解决问题。
其次如果孟竹有必胜条件的话,那么异或值肯定不能为0。反过来算,求有多少个异或为0然后用C[n][2]剪掉即可。
怎么算呢?很简单,计算所有的前缀异或值。比如当前的前缀异或为A,之前到第j个位置异或也为A,A^A = 0 ,于是j+1 -> 当前位置这段区间的异或就为0
对于0的情况要特殊讨论,因为如果前缀和 <=k 的话异或为0是要加一的否则不加
int n ;
const int N = 1e5 + 9;
LL a[N];
map<LL , LL> hash;
LL k , sum , ans;
void solve(){
    RD(n);
    RD(k);
    for (int i = 0 ; i < n ; ++i)
        RD(a[i]);
    hash.clear();
    hash[0] = 0;
    int tail = 0;
    ans = 0;
    sum = 0;
    LL xorsum = 0 , xortail = 0;
    LL ALL = 0;
    for (int i = 0 ; i < n ; ++i){
        sum += a[i];
        xorsum ^= a[i];
        if (hash.find(xorsum) == hash.end()) hash[ xorsum ] = 1;
        else hash[ xorsum ] = hash[ xorsum ] + 1;
        while (sum > k) {
                sum -= a[tail];

//                if(hash.find(xortail) == hash.end()) printf("%d %d\n" , i , tail);
                assert(hash.find(xortail) != hash.end());
                xortail ^= a[tail];
                hash[xortail] = hash[xortail ]  - 1;

                ++tail;
        }
        ALL += i - tail + 1;
//        if (hash.find(xorsum) != hash.end())
        assert(hash.find(xorsum) != hash.end());
        if (tail == 0) ++ hash[0];
        else ++hash[(xortail)];
        if (tail <= i)
            ans += hash[ xorsum ] - 1ll;
        if (tail == 0) -- hash[0];
        else --hash[(xortail)];
//        cout <<"ANS:" <<  ans << endl;
    }
//    cout << ALL <<endl;
    ans = ALL - ans;
    OT(ans);
}
int main(){
//    freopen("0.in" , "r" , stdin);
//    freopen("0.out" , "w" , stdout);
    Rush solve();
}


F 孟竹要减肥?

并查集
将所有边长计算出来,从小到大加边,用并查集统计连通性,如果有一个 >= m 的连通块就结束
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include<math.h>
using namespace std;
const int N = 600;
namespace ufset{
    int fa[N] , rank[N] , SZ[N];
    void init(){
        for (int i = 0 ; i < N ; ++i) SZ[i] = 1 , fa[i] = i , rank[i] = 0;
    }
    int findset(int x){
        int r = x , y ;
        while(fa[r] != r) r = fa[r];
        while(fa[x] != r) {y = fa[x] , fa[x] = r , x = y;}
        return r;
    }
    void __unionset(int x , int y){
        if (rank[x] > rank[y]) {
                fa[y] = x;
                SZ[x] += SZ[y];
        }
        else {
            fa[x] = y;
            SZ[y] += SZ[x];
            if (rank[x] == rank[y]) ++ rank[y];
        }
    }
    void unionset(int x , int y){
        int rx = findset(x) , ry = findset(y);
        if (rx != ry) __unionset(rx , ry);
    }
}using namespace ufset;
struct Point{
    double x , y;
    void input(){
        scanf("%lf%lf" , &x , &y);
    }
    #define sqr(x) ((x) * (x))
    double dis(const Point & A) const{
        return sqrt(sqr(x - A.x) + sqr(y - A.y));
    }
}p[509];
int n , m ;
const double eps = 1e-8;
int dcmp(double d){
    if (fabs(d) < eps) return 0;
    return d < 0 ? -1 : 1;
}
struct Rel{
    int p , q;
    double nk;
    bool operator < (const Rel & A) const{
        return dcmp(nk - A.nk) < 0;
    }
}relation[509 * 509];
void solve(){
    scanf("%d%d" , &n,&m);
    for (int i = 0 ; i < n ; ++i) p[i].input();
    int rcnt = 0;
    for (int i = 0 ; i < n ; ++i)
    for (int j = i + 1 ; j < n ; ++j){
        relation[rcnt].p = i;
        relation[rcnt].q = j;
        relation[rcnt].nk = p[i].dis(p[j]);
        rcnt++;
    }
    sort(relation , relation + rcnt);
    init();
    for (int i = 0 ; i < rcnt ; ++i){
        unionset(relation[i].p , relation[i].q);
        int rx = findset(relation[i].p) , ry = findset(relation[i].q);
        if (SZ[rx] >= m || SZ[ry] >= m){
            printf("%.4lf\n" , relation[i].nk);
            return;
        }
    }
}
int main(){
    freopen("0.in" , "r" , stdin);
    freopen("0.out" , "w" , stdout);
    int T;
    scanf("%d" , &T);
    while(T--) solve();
}

G 孟竹的星星

水题。
标程的算法是计算出外心,然后随便找一个点,每次旋转72度即可。
看xlk的代码:
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<vector>
#include<math.h>
using namespace std;
#define fr(i,n) for(int i=0;i<n;i++)
#define fo(i,n) for(int i=1;i<=n;i++)
#define fe(i,n) for(__typeof(n.begin()) i=n.begin();i!=n.end();i++)
 
    const double eps=1e-4;
    const double pi=acos(-1.);
    struct P
    {
        double x,y;
        P(){}
        P(double x,double y):x(x),y(y){}
        void scan()
        {
            scanf("%lf %lf",&x,&y);
        }
        void print(string s="")
        {
            if(s!="")
                cout << s << ": ";
            printf("%.2f %.2f\n",x,y);
        }
        double dis(const P&a)
        {
            return hypot(x-a.x,y-a.y);
        }
        P rot(double f)
        {
            double sf=sin(f),cf=cos(f);
            return P(x*cf-y*sf,y*cf+x*sf);
        }
        double dot(const P&a)
        {
            return x*a.x+y*a.y;
        }
        double det(const P&a)
        {
            return x*a.y-y*a.x;
        }
    };
    bool operator==(const P&a,const P&b)
    {
        return fabs(a.x-b.x)<eps&&fabs(a.y-b.y)<eps;
    }
    bool operator!=(const P&a,const P&b)
    {
        return !(a==b);
    }
    bool operator<(const P&a,const P&b)
    {
        if(fabs(a.x-b.x)<eps)
            return a.y<b.y;
        return a.x<b.x;
    }
    P operator+(const P&a,const P&b)
    {
        return P(a.x+b.x,a.y+b.y);
    }
    P operator-(const P&a,const P&b)
    {
        return P(a.x-b.x,a.y-b.y);
    }
    P operator/(const P&a,double f)
    {
        return P(a.x/f,a.y/f);
    }
    P operator*(const P&a,double f)
    {
        return P(a.x*f,a.y*f);
    }
    int sgn(double x)
    {
        return x<-eps?-1:x>eps;
    }
    namespace triangle
    {
        P circumcenter(const P&a,const P&b,const P&c)
        {
            double x1=a.x,y1=a.y,x2=b.x,y2=b.y,x3=c.x,y3=c.y;
            double s1=x1*x1+y1*y1,s2=x2*x2+y2*y2,s3=x3*x3+y3*y3;
            double rx=(y1*(s2-s3)+y2*(s3-s1)+y3*(s1-s2))/(x1*(y2-y3)+x2*(y3-y1)+x3*(y1-y2));
            double ry=(x1*(s2-s3)+x2*(s3-s1)+x3*(s1-s2))/(x1*(y2-y3)+x2*(y3-y1)+x3*(y1-y2));
            return P(-rx/2,ry/2);
        }
        P barycenter(const P&a,const P&b,const P&c)
        {
            return (a+b+c)/3;
        }
        pair<P,double>excircle(const P&a,const P&b,const P&c)
        {
            P p=circumcenter(a,b,c);
            return make_pair(p,p.dis(a));
        }
    }
int main()
{
    int t,ss;
    P a,b,c,d,e,w,r,p[5],s[3];
    for(scanf("%d",&t);t--;)
    {
        a.scan();
        b.scan();
        c.scan();
        w=triangle::circumcenter(a,b,c);
        r=w-a;
        ss=0;
        p[0]=a;
        for(int i=1;i<5;i++)
            p[i]=(p[i-1]-w).rot(2*pi/5)+w;
        for(int i=0;i<5;i++)
            if(p[i]!=a&&p[i]!=b&&p[i]!=c)
                s[ss++]=p[i];
        sort(s,s+ss);
        for(int i=0;i<2;i++)
            s[i].print();
    }
    return 0;
}

H 孟竹开Party

其实本题本意是想藏起来DLX算法然后让大家用图论方法搞不定的。。。但是貌似图论也可以
先说标程解法——用一遍dfs(复杂度O(VE))来计算出来每个人直接 /  间接能Hold 住的人,然后就是 经典的可重复覆盖问题 。 中间如果一个人选择了,那么他的配偶就不能选择。
const int head=0;
//const int INF=10000000;
const int maxn = 610;
const int maxd = 1000000;
int N, M, K,  cnt, res;
int mat[maxn][maxn], s[maxn], l[maxd], r[maxd], u[maxd], d[maxd], c[maxd], o[maxn], row[maxd];
bool use[maxn];
void makegragh(int &n, int &m)
{
    memset(mat, 0, sizeof(mat));
//初始化mat矩阵
}
void initial(int n, int m)
{
    memset(use, false, sizeof(use));
    res=n+1;
    int i, j, rowh;
    memset(s, 0, sizeof(s));
    for(i=head; i<=m; i++)
    {
        r[i]=(i+1)%(m+1);
        l[i]=(i-1+m+1)%(m+1);
        u[i]=d[i]=i;
    }
    cnt=m+1;
    for(i=1; i<=n; i++)
    {
        rowh=-1;
        for(j=1; j<=m; j++)
        {
            //printf("%d", mat[i][j]);
            if(mat[i][j])
            {
                s[j]++;
                u[cnt]=u[j];
                d[u[j]]=cnt;
                u[j]=cnt;
                d[cnt]=j;
                row[cnt]=i;
                c[cnt]=j;
                if(rowh==-1)
                {
                    l[cnt]=r[cnt]=cnt;
                    rowh=cnt;
                }
                else
                {
                    l[cnt]=l[rowh];
                    r[l[rowh]]=cnt;
                    r[cnt]=rowh;
                    l[rowh]=cnt;
                }
                cnt++;
            }
        }
        //puts("");
    }
}
void remove(int c)
{
    for(int i=d[c]; i!=c; i=d[i])
    {
        r[l[i]]=r[i];
        l[r[i]]=l[i];
    }
}
void resume(int c)
{
    for(int i=d[c]; i!=c; i=d[i])
        r[l[i]]=l[r[i]]=i;
}
int h()
{
    bool has[maxn];
    memset(has, false, sizeof(has));
    int ans=0;
    for(int i=r[head]; i!=head; i=r[i])
        if(!has[i])
        {
            ans++;
            for(int j=d[i]; j!=i; j=d[j])
                for(int k=r[j]; k!=j; k=r[k])
                    has[c[k]]=true;
        }
    return ans;
}
int marrige[maxn];
bool dfs(int k)
{
    if(k+h()>=res)return false;//A* cut

    if(r[head]==head)
    {
        if(k<res) res=k;
        return true;
    }
    int ms=INF, cur=0;
    for(int t=r[head]; t!=head; t=r[t])
        if(s[t]<ms)
        {
            ms=s[t];
            cur=t;
        }
    for(int i=d[cur]; i!=cur; i=d[i])
    {
        int rr = row[i];
        if (marrige[rr] == 0 || use[marrige[rr]] == 0) use[rr] = 1;
        else continue;
//        int rr = (row[i] - 1) / 2 + 1;
//        if (!use[rr]) use[rr] = true;
//        else continue;
        remove(i);
        for(int j=r[i]; j!=i; j=r[j])
        {
            remove(j);
            s[c[j]]--;
        }
        dfs(k+1);
        for(int j=l[i]; j!=i; j=l[j])
        {
            resume(j);
            s[c[j]]++;
        }
        use[rr] = false;
        resume(i);
    }
    return false;
}
int n , m;
int P , x , y;
VI edge[maxn];
void vdfs(int now , int x){
    mat[x][now] = 1;
    ECH(it , edge[now]){
        int go = *it;
        if (!mat[x][go]) vdfs(go , x);
    }
}
void solve(){
    RST(marrige);
    RST(mat);
    RD(n , m);
//    printf("%d %d :" , n , m);
    for (int i = 1 ; i <= n + m ; ++i) edge[i].clear();
    for (int i = 1 ; i <= n + m ; ++i)
        edge[i].PB(i);
    RD(P);
    DO(P){
        RD(x , y);
        //mat[x][n + y] = 1;
        edge[x].PB(n + y);
    }
    RD(P);
    DO(P){
        RD(x , y);
        //mat[n + x][y] = 1;
        edge[n + x].PB(y);
    }
    RD(P);
    DO(P){
        RD(x , y);
        marrige[x] = y + n;
        marrige[y + n] = x;
    }
    for(int i = 1 ; i <= n + m ; ++i){
        vdfs(i , i);
    }
//    for (int i = 1 ; i <= n + m ; ++i){
//        for (int j = 1 ; j <= n + m ; ++j)
//            printf("%d " , mat[i][j]);
//        cout << endl;
//    }
    initial(n + m , n + m);
//    cout << "DS" << endl;
    dfs(0);
    cout << res << endl;
}
int main(){
    freopen("0.in" , "r" , stdin);
    freopen("0.out" , "w" , stdout);
    Rush solve();
}

XLK童鞋的解法是:计算出所有强连通块儿,如果每个入度为0的scc大小都大于1,那么一定有解。贪心就是看只有一个点的scc必须取。。然后如果他有情侣。。他情侣的scc就把他情侣去掉。。一直这样。。看看会不会出现擦掉之后他情侣的scc就没有别的点了
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
using namespace std;
#define fr(i,n) for(int i=0;i<n;i++)
#define fo(i,n) for(int i=1;i<=n;i++)
#define fe(i,n) for(__typeof(n.begin()) i=n.begin();i!=n.end();i++)
int t,n,m,p,q,w,scc,x,y,in[2020];
int low[2020],dfn[2020],cnt;
int v[2020],r[2020],s[2020],ss;
int f[2020],z;
vector<int>a[2020];
set<int>se[2020];
int dfs(int x)
{
    dfn[x]=low[x]=++cnt;
    s[ss++]=x;
    v[x]=1;
    fe(i,a[x])
    {
        if(!dfn[*i])
        {
            dfs(*i);
            low[x]=min(low[x],low[*i]);
        }
        else if(v[*i])
        {
            low[x]=min(low[x],dfn[*i]);
        }
    }
    if(dfn[x]==low[x])
    {
        scc++;
        do
        {
            v[s[ss-1]]=0;
            r[s[ss-1]]=scc;
            se[scc].insert(s[ss-1]);
//          c[scc]++;
        }
        while(s[--ss]!=x);
    }
    return 0;
}
int main()
{
    for(scanf("%d",&t);t--;)
    {
        scc=0;
        cnt=0;
        z=0;
        memset(in,0,sizeof in);
        memset(f,0,sizeof f);
        memset(low,0,sizeof low);
        memset(dfn,0,sizeof dfn);
        memset(v,0,sizeof v);
        memset(r,0,sizeof r);
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m+n;i++)
            a[i].clear();
        for(int i=1;i<=m+n;i++)
            se[i].clear();
        scanf("%d",&p);
        for(int i=0;i<p;i++)
        {
            scanf("%d%d",&x,&y);
            a[x].push_back(y+n);
        }
        scanf("%d",&q);
        for(int i=0;i<q;i++)
        {
            scanf("%d%d",&x,&y);
            a[x+n].push_back(y);
        }
        scanf("%d",&w);
        for(int i=0;i<w;i++)
        {
            scanf("%d%d",&x,&y);
            f[x]=y+n;
            f[y+n]=x;
        }
        for(int i=1;i<=m+n;i++)
            if(!dfn[i])
                dfs(i);
        queue<int>q;
        for(int i=1;i<=m+n;i++)
            fe(j,a[i])
                if(r[i]!=r[*j])
                    in[r[*j]]++;
        for(int i=1;i<=m+n;i++)
            if(se[r[i]].size()==1&&in[r[i]]==0)
                q.push(i);
        for(int i=1;i<=scc;i++)
            if(in[i]==0)
                z++;
        while(q.size())
        {
            int u=q.front();
            q.pop();
            if(f[u]&&in[r[f[u]]]==0)
            {
                se[r[f[u]]].erase(f[u]);
                if(se[r[f[u]]].size()==0)
                {
                    printf("%d\n",n+m+1);
                    goto end;
                }
                else if(se[r[f[u]]].size()==1)
                {
                    q.push(*se[r[f[u]]].begin());
                }
            }
        }
        printf("%d\n",z);
        end:;
    }
}

I 孟竹画圈圈诅咒你

没啥好说的,标准数学题。
typedef long long int64;

struct Int {
	int x;
	Int() :
			x(0) {
	}
	Int(int _x) :
			x(_x) {
		x %= MOD;
		if (x < 0)
			x += MOD;
	}
	Int(int64 _x) {
		x = _x % MOD;
		if (x < 0)
			x += MOD;
	}
	static Int get(int x) {
		Int a;
		a.x = x;
		return a;
	}

	Int operator+(const Int&o) const {
		int t = x + o.x;
		if (t >= MOD)
			t -= MOD;
		return get(t);
	}
	Int operator*(const Int&o) const {
		return get(1LL * x * o.x % MOD);
	}
	Int operator-(const Int&o) const {
		int t = x - o.x;
		if (t < 0)
			t += MOD;
		return get(t);
	}
	Int operator/(const Int&o) const {
		return (*this) * o.inv();
	}
	Int&operator+=(const Int&o) {
		return (*this) = *this + o;
	}
	Int&operator-=(const Int&o) {
		return (*this) = *this - o;
	}
	Int&operator*=(const Int&o) {
		return (*this) = *this * o;
	}
	Int&operator/=(const Int&o) {
		return (*this) = *this / o;
	}

	Int power(int64 n) const {
		if (!n)
			return get(1);
		const Int&a = *this;
		if (n & 1)
			return power(n - 1) * a;
		else
			return (a * a).power(n >> 1);
	}

	Int inv() const {
		return power(MOD - 2);
	}
};

/* .................................................................................................................................. */
Int D(Int n){
    Int ret;
    ret = n * (n + 1) / 2;
    ret = ret + 1;
    return ret;
}
void solve(){
    char op[2];
    Int n , ans;
    scanf("%s%d" , op , &n.x);
    if (op[0] == 'L'){
        ans = D(n);
        //cout << ans.x << endl;
        OT(ans.x);
    }
    else if (op[0] == 'V'){
        ans = D(n * 2);
        ans = ans - n * 2;
        //cout << ans.x << endl;
        OT(ans.x);
    }
    else if (op[0] == 'Z'){
        ans = D(n * 3);
        ans = ans - n * 5;
        //cout << ans.x << endl;
        OT(ans.x);
    }
}
int main(){
    freopen("0.in" , "r" , stdin);
    freopen("0.out" , "w" , stdout);
    Rush solve();
}

cxlove 的代码:
#include<iostream>
#include<cstdio>
#include<map>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
#include<set>
#include<string>
#include<queue>
#define inf 1000000005
#define M 40
#define N 100005
#define maxn 300005
#define eps 1e-12
#define zero(a) fabs(a)<eps
#define Min(a,b) ((a)<(b)?(a):(b))
#define Max(a,b) ((a)>(b)?(a):(b))
#define pb(a) push_back(a)
#define mp(a,b) make_pair(a,b)
#define mem(a,b) memset(a,b,sizeof(a))
#define LL long long
#define MOD 1000000009
#define lson step<<1
#define rson step<<1|1
#define sqr(a) ((a)*(a))
#define Key_value ch[ch[root][1]][0]
#define test puts("OK");
#define pi acos(-1.0)
#define lowbit(x) ((-(x))&(x))
#define HASH1 1331
#define HASH2 10001
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
LL a,b,c;
int main(){
    //freopen("input.txt","r",stdin);
    int  t;
    char str[10];
    cin>>t;
    while(t--){
        scanf("%s%d" , str , &a);
        LL ans;
        if(str[0]=='L') ans=(a*(a+1)/2 + 1)%MOD;
        else if(str[0]=='V') ans=(2*a*(2*a+1)/2+1-2*a)%MOD;
        else ans=(3*a*(3*a+1)/2+1-5*a)%MOD;
        cout<<ans<<endl;
    }
    return 0;
}

J 孟竹搭积木

这题数据有错误貌似,大家抱歉了。
方法是状态压缩DP + 矩阵乘法 + 枚举 + 记忆化搜索
先说做法吧——
1、状态压缩,把一层的占有方法用2^7的一个向量记录。
2、暴力枚举第一层的情况,将只有一层的每个状态拼接方法数计算出来——initial P
3、记忆化搜索+枚举计算出转移矩阵Q,即从i层状态转移到第i层填满并且i+1层的另一个状态的转移方案数——initial Q
4、矩阵乘法,计算 P * (E + Q + Q^2 +... + Q^(N))
我的代码(虽然有错,方法是对的T_T)
const int MATN = 129;
const LL modo = MOD;
struct Mat{
    int Matn , Matm;
    LL a[MATN][MATN];
    Mat(){
        Matn = 0;
        Matm = 0;
        memset(a , 0 , sizeof(a));
    }
    void output(){
        cout << "OUTPUT" << endl;
        for (int i = 0 ; i < Matn ; ++i){
            for (int j = 0 ; j < Matm ; ++j){
                printf("%lld ",a[i][j]);
            }
            printf("\n");
        }
    }
    void init(){
        Matn = 0;Matm = 0;
        memset(a , 0 , sizeof(a));
    }
    Mat operator + (const Mat & A) const{
        Mat ret = A;
        for (int i = 0 ; i < Matn ; ++i){
            for (int j = 0 ; j < Matm ; ++j)
                ret.a[i][j] = (ret.a[i][j] + a[i][j]) % modo;
        }
        return ret;

    }
    Mat operator * (const Mat & A) const{
        Mat c ;
        c.Matn = Matn;
        c.Matm = A.Matm;
        for (int i = 0 ; i < Matn ; ++i)
            for (int j = 0 ; j < A.Matm ; ++j)
                for (int k = 0 ; k < Matm ; ++k)
                    c.a[i][j] = (c.a[i][j] + (a[i][k] * A.a[k][j])%modo)%modo;
        return c;
    }
    void initI(){
        memset(a, 0 , sizeof(a));
        for (int i = 0 ; i < Matn ; ++i)
            a[i][i] = 1;
    }
    Mat power(LL k){
        Mat c = *this  , b;
        b.init();
        b.Matn = Matn ; b.Matm = Matm;
        b.initI();
        while(k){
            if (k & 1LL)
                b = b * c;
            c = c * c;
            k >>= 1LL;
        }
        return b;
    }
}QQ;
struct ZHU{
    Mat a[2][2];
    void init(const Mat& p){
        for (int i = 0 ; i < 2 ; ++i)
            for (int j=  0 ; j < 2 ;++j){
                a[i][j].init();
                a[i][j].Matn = 128 ; a[i][j].Matm = 128;
            }
        a[0][0] = p;
        a[0][1].initI();
        a[1][1].initI();
    }
    void initI(){
        for (int i = 0 ; i < 2 ; ++i)
            for (int j=  0 ; j < 2 ;++j){
                a[i][j].Matn = 128 ; a[i][j].Matm = 128;
                a[i][i].initI();
            }
    }
    ZHU operator * (const ZHU & A) const{
        ZHU res;
        for (int i = 0 ; i < 2 ; ++i)
            for (int j= 0 ; j < 2 ;++j){
                res.a[i][j].init();
                res.a[i][j].Matn = 128 ; res.a[i][j].Matm = 128;
            }
        for (int i = 0 ; i < 2 ; ++i)
            for (int j = 0 ; j < 2 ; ++j)
                for (int k = 0 ; k < 2 ; ++k)
                    res.a[i][j] = (res.a[i][j] + a[i][k] * A.a[k][j]);
        return res;
    }
    void copy(const ZHU & A) {
        for(int i = 0 ; i < 2 ; ++i)
            for (int j = 0 ; j < 2 ; ++j)
                a[i][j] = A.a[i][j];
    }
    Mat power(LL k);
}R , nR , b , c;
Mat ZHU::power(LL k){
//    printf("\nINT ");
//    cout << k << endl;
    c = *this;
    bool f = false;
    while(k){
        if (k & 1LL){
            if (!f) b = c;
            else b = b * c;
            f = true;
        }
        c = c * c;
        k >>= 1LL;
    }
    if (!f){
        b = c;
        b.a[0][1].initI();
    }
    return b.a[0][1];
}
const int PCODE[] = {0 , 1 , 2 , 4 , 8 , 16 , 32 , 64 , 0};
struct Under{
    bool mp[3][3];
    int hash;
    int encode(){
        hash = 0;
        for (int i = 0 ; i < 3 ; ++i)
            for(int j = 0 ; j < 3 ; ++j)
                if (mp[i][j])
                    hash |= PCODE[i * 3 + j];
        return hash;
    }
    void decode(){
        RST(mp);
        for (int i = 0 ; i < 3 ; ++i)
        for(int j = 0 ; j < 3 ; ++j){
            if (i + j == 0 || i + j == 4) continue;
            if (hash & (PCODE[i * 3 + j]))
                mp[i][j] = true;
            else mp[i][j] = false;
        }
    }
    void output(){
        printf("  %d %d\n", mp[0][1] , mp[0][2]);
        printf("%d %d %d\n" , mp[1][0] , mp[1][1] , mp[1][2]);
        printf("%d %d\n", mp[2][0] , mp[2][1]);
    }
    void input(){
        for(int i = 0 ; i < 3 ; ++i)
        for (int j = 0 ; j < 3 ; ++j){
            if (i + j == 0 || i + j == 4) continue;
            int x;
            RD(x);
            mp[i][j] = x;
        }
        encode();
    }

}en , temp;
LL n;
Mat P , Q ;
void solve(){
    RD(n);
    en.input();
    Mat nP = P;
//    nP.output();
    nR.copy(R);
//    nR.a[0][1].output();
//    printf("N %lld\n" , n);
    QQ = nR.power(n);
//    cout << "DS" << endl;
    nP = nP * QQ;
    printf("%lld\n" , nP.a[0][en.hash]);
}
bool inmap(int x , int y){
    if (x + y == 0) return false;
    if (x + y == 4) return false;
    return 0 <= x && x < 3 && 0 <= y && y < 3;
}
int canput(int bi , int x , int y , int d){
    temp.hash = bi;
    temp.decode();
    if (!inmap(x , y) || !inmap(x + dx4[d] , y + dy4[d]) || !inmap(x + dx4[(d + 1) % 4] , y + dy4[(d + 1) % 4])) return -1;
    if (!temp.mp[x][y] || !temp.mp[x + dx4[d]][y + dy4[d]] || !temp.mp[x + dx4[(d + 1) % 4]][y + dy4[(d + 1) % 4]]) return -1;
    temp.mp[x][y] = 0;
    temp.mp[x + dx4[d]][y + dy4[d]] = 0;
    temp.mp[x + dx4[(d + 1) % 4]][y + dy4[(d + 1) % 4]] = 0;
    return temp.encode();
}
int takeOut(int bi , int x , int y , int d){
    temp.hash = bi;
    temp.decode();
    temp.mp[x][y] = 0;
    temp.mp[x + dx4[d]][y + dy4[d]] = 0;
    temp.mp[x + dx4[(d + 1) % 4]][y + dy4[(d + 1) % 4]] = 0;
    return temp.encode();
}
bool canput2(int bi , int x , int y , int d , int x1 , int y1 , int d1){
    temp.hash = bi;
    temp.decode();
    if (!inmap(x , y) || !inmap(x + dx4[d] , y + dy4[d]) || !inmap(x + dx4[(d + 1) % 4] , y + dy4[(d + 1) % 4])) return false;
    if (!temp.mp[x][y] || !temp.mp[x + dx4[d]][y + dy4[d]] || ! temp.mp[x + dx4[(d + 1) % 4]][y + dy4[(d + 1) % 4]]) return false;
    temp.mp[x][y] = 0;
    temp.mp[x + dx4[d]][y + dy4[d]] = 0;
    temp.mp[x + dx4[(d + 1) % 4]][y + dy4[(d + 1) % 4]] = 0;
    if (!inmap(x1 , y1) || !inmap(x1 + dx4[d1] , y1+ dy4[d1]) || !inmap(x1 + dx4[(d1 + 1) % 4] , y1 + dy4[(d1 + 1) % 4])) return false;
    if (!temp.mp[x1][y1] || !temp.mp[x1 + dx4[d1]][y1 + dy4[d1]] || ! temp.mp[x1 + dx4[(d1 + 1) % 4]][y1 + dy4[(d1 + 1) % 4]]) return false;
    temp.mp[x1][y1] = 0;
    temp.mp[x1 + dx4[d1]][y1 + dy4[d1]] = 0;
    temp.mp[x1 + dx4[(d1 + 1) % 4]][y1 + dy4[(d1 + 1) % 4]] = 0;
    return temp.encode() == 0;

}
void initialP(){
    P.init();
    P.Matn = 1 , P.Matm = 128;
    for (int i = 0 ; i < 128 ; ++i)
        for (int j = 0 ; j < 3 ; ++j)
            for (int k = 0 ; k < 3 ; ++k)
                for (int d = 0 ; d < 4 ; ++d){
                    int res = canput(i , j , k , d);
                    if (res == 0)
                        ++P.a[0][i];
                }
    for (int i = 0 ; i < 128 ; ++i)
        for (int j = 0 ; j < 3 ; ++j)
            for (int k = 0 ; k < 3 ; ++k)
                for (int d = 0 ; d < 4 ; ++d)
        for (int j1 = i ; j1 < 3 ; ++j1)
            for (int k1 = j ; k1 < 3 ; ++k1)
                for (int d1 = 0 ; d1 < 4 ; ++d1){
                    bool res = (canput2(i , j , k , d , j1 , k1 , d1));
                    if (res)
                        ++P.a[0][i];
                }
//    for (int i = 0 ; i < 128 ; ++i)
//    if (P.a[0][i] == 2){
//        temp.hash = i;
//        temp.decode();
//        temp.output();
//    }
}
vector< PII > memory[129][129];
bool has(int bi , int bb){
    int res = bi & bb;
    return res == bb;
}
int ok[129][129];
bool canPush(int down , int up){
//    printf("PRE : %d %d\n" , down , up);
    if(down + up == 0) {
            ok[down][up] = 1;
            return 1;
    }
//    printf("%d\n" , ok[down][up]);
    if (ok[down][up] != -1) return ok[down][up];

//    printf("NEX : %d %d\n" , down , up);
    //if (memory[down][up] != -1) return memory[down][up];
    for (int i = 0 ; i < 3 ; ++i)
    for (int j = 0 ; j < 3 ; ++j)
    for (int d = 0 ; d < 4 ; ++d){
        int res = canput(down , i , j , d);
        if (res != -1){
            int newdown = res;
            if (canPush(newdown , up)){
                memory[down][up].PB(MP(newdown , up));
                //return 1;
            }
        }
    }
    for (int i = 0 ; i < 3 ; ++i)
    for (int j = 0 ; j < 3 ; ++j)
    for (int d = 0 ; d < 4 ; ++d){
        int res = canput(up , i , j , d);
        if (res != -1){
            int newup = res;
            if (canPush(down , newup)){
                memory[down][up].PB(MP(down , newup));
//                return 1;
            }
        }
    }
    /**
            1   2
        4   8   16
        32  64
    */
    if (has(down , 3) && has(up , 1))
        if (canPush(down - 3 , up - 1)){
            memory[down][up].PB(MP(down - 3 , up - 1));}// = 1 ; return 1;}
    if (has(down , 3) && has(up , 2))
        if (canPush(down - 3 , up - 2)){
            memory[down][up].PB(MP(down - 3 , up - 2));}// = 1 ; return 1;}
    if (has(down , 12) && has(up , 4))
        if (canPush(down - 12 , up - 4)){
            memory[down][up].PB(MP(down - 12 , up - 4));}// = 1 ; return 1;}
    if (has(down , 12) && has(up , 8))
        if (canPush(down - 12 , up - 8)){
            memory[down][up].PB(MP(down - 12 , up - 8));}// = 1 ; return 1;}
    if (has(down , 24) && has(up , 8))
        if (canPush(down - 24 , up - 8)){
            memory[down][up].PB(MP(down - 24 , up - 8));}// = 1 ; return 1;}
    if (has(down , 24) && has(up , 16))
        if (canPush(down - 24 , up - 16)){
            memory[down][up].PB(MP(down - 24 , up - 16));}// = 1 ; return 1;}
    if (has(down , 96) && has(up , 32))
        if (canPush(down - 96 , up - 32)){
            memory[down][up].PB(MP(down - 96 , up - 32));}// = 1 ; return 1;}
    if (has(down , 96) && has(up , 64))
        if (canPush(down - 96 , up - 64)){
            memory[down][up].PB(MP(down - 96 , up - 24));}// = 1 ; return 1;}
    /**
            1   2
        4   8   16
        32  64
    */
    if (has(down , 36) && has(up , 4))
        if (canPush(down - 36 , up - 4)){
            memory[down][up].PB(MP(down - 36 , up - 4));}// = 1 ; return 1;}
    if (has(down , 36) && has(up , 32))
        if (canPush(down - 36 , up - 32)){
            memory[down][up].PB(MP(down - 36 , up - 32));}// = 1 ; return 1;}
    if (has(down , 9) && has(up , 1))
        if (canPush(down - 9 , up - 1)){
            memory[down][up].PB(MP(down - 9 , up - 1));}// = 1 ; return 1;}
    if (has(down , 9) && has(up , 8))
        if (canPush(down - 9 , up - 8)){
            memory[down][up].PB(MP(down - 9 , up - 8));}// = 1 ; return 1;}
    if (has(down , 72) && has(up , 8))
        if (canPush(down - 72 , up - 8)){
            memory[down][up].PB(MP(down - 72 , up - 8));}// = 1 ; return 1;}
    if (has(down , 72) && has(up , 64))
        if (canPush(down - 72 , up - 64)){
            memory[down][up].PB(MP(down - 72 , up - 64));}// = 1 ; return 1;}
    if (has(down , 18) && has(up , 2))
        if (canPush(down - 18 , up - 2)){
            memory[down][up].PB(MP(down - 18 , up - 2));}// = 1 ; return 1;}
    if (has(down , 18) && has(up , 16))
        if (canPush(down - 18 , up - 16)){
            memory[down][up].PB(MP(down - 18 , up - 16));}// = 1 ; return 1;}


    /**
            1   2
        4   8   16
        32  64
    */
    if (has(up , 3) && has(down , 1))
        if (canPush(down - 1 , up - 3 )){
            memory[down][up].PB(MP(down - 1 , up - 3));}// = 1 ; return 1;}
    if (has(up , 3) && has(down , 2))
        if (canPush(down - 2 , up - 3)){
            memory[down][up].PB(MP(down - 2 , up - 3));}// = 1 ; return 1;}
    if (has(up , 12) && has(down , 4))
        if (canPush(down - 4 , up - 12)){
            memory[down][up].PB(MP(down - 4 , up - 12));}// = 1 ; return 1;}
    if (has(up , 12) && has(down , 8))
        if (canPush(down - 8 , up - 12)){
            memory[down][up].PB(MP(down - 8 , up - 12));}// = 1 ; return 1;}
    if (has(up , 24) && has(down , 8))
        if (canPush(down - 8 , up - 24)){
            memory[down][up].PB(MP(down - 8 , up - 24));}// = 1 ; return 1;}
    if (has(up , 24) && has(down , 16))
        if (canPush(down - 16 , up - 24)){
            memory[down][up].PB(MP(down - 16 , up - 24));}// = 1 ; return 1;}
    if (has(up , 96) && has(down , 32))
        if (canPush(down - 32 , up - 96)){
            memory[down][up].PB(MP(down - 32 , up - 96));}// = 1 ; return 1;}
    if (has(up , 96) && has(down , 64))
        if (canPush(down - 64 , up - 96)){
            memory[down][up].PB(MP(down - 64 , up - 96));}// = 1 ; return 1;}
    /**
            1   2
        4   8   16
        32  64
    */
    if (has(up , 36) && has(down , 4))
        if (canPush(down - 4 , up - 36)){
            memory[down][up].PB(MP(down - 4 , up - 36));}// = 1 ; return 1;}
    if (has(up , 36) && has(down , 32))
        if (canPush(down - 32 , up - 36)){
            memory[down][up].PB(MP(down - 32 , up - 36));}// = 1 ; return 1;}
    if (has(up , 9) && has(down , 1))
        if (canPush(down - 1 , up - 9)){
            memory[down][up].PB(MP(down - 1 , up - 9));}// = 1 ; return 1;}
    if (has(up , 9) && has(down , 8))
        if (canPush(down - 8 , up - 9)){
            memory[down][up].PB(MP(down - 8 , up - 9));}// = 1 ; return 1;}
    if (has(up , 72) && has(down , 8))
        if (canPush(down - 8 , up - 72)){
            memory[down][up].PB(MP(down - 8 , up - 72));}// = 1 ; return 1;}
    if (has(up , 72) && has(down , 64))
        if (canPush(down - 64 , up - 72)){
            memory[down][up].PB(MP(down - 64 , up - 72));}// = 1 ; return 1;}
    if (has(up , 18) && has(down , 2))
        if (canPush(down - 2 , up - 18)){
            memory[down][up].PB(MP(down - 2 , up - 18));}// = 1 ; return 1;}
    if (has(up , 18) && has(down , 16))
        if (canPush(down - 16 , up - 18)){
            memory[down][up].PB(MP(down - 16 , up - 18));}// = 1 ; return 1;}
    ok[down][up] = (SZ(memory[down][up]) > 0);
    return SZ(memory[down][up]) > 0;
}
vector<PII> cmp1 , cmp2;
struct ME{
    vector<PII> del;
    ME(){
        del.clear();
    }
    void rush(){
        sort(ALL(del));
    }
    bool operator < (const ME & A) const{
        cmp1 = del;
        cmp2 = A.del;
        sort(ALL(cmp1));
        sort(ALL(cmp2));
        //if (SZ(cmp1) != SZ(cmp2)) return SZ(cmp1) < SZ(cmp2);
        for (int i = 0 ; i < min(SZ(cmp1) , SZ(cmp2)) ; ++i)
            if (cmp1[i] != cmp2[i])
                return cmp1[i] < cmp2[i];
        return false;
    }
    bool operator == (const ME & A) const{
        return (!(*this < A) && !(A < *this));
    }
};
vector<ME> mycnt;
vector<PII> :: iterator iter;
ME now;
void cnt(int down , int up){
//    printf("PRE %d %d\n" , down , up);
    if(down == 0 && up == 0){
            mycnt.PB(now);
            return;
    }
    if (ok[down][up] == 0) return;
//    printf("CNT: %d %d\n" , down , up);
//    cout << SZ(memory[down][up]) << endl;
    for(int i = 0 ; i < SZ(memory[down][up]) ;++i){
            int newdown = memory[down][up][i].fi;
            int newup = memory[down][up][i].se;
//        printf("-%d %d\n", newdown , newup);
        now.del.PB( MP(down - newdown , up - newup) );
//        printf("+ %d %d\n" , down - newdown , up - newup);
        cnt(newdown , newup);
        iter = now.del.end() - 1;
        //iter--;
//        printf("- %d %d\n" , iter->fi , iter->se);
        now.del.erase(iter);//( MP(down - newdown , up - newup) );
    }
}
void initialQ(){
    Q.init();
    Q.Matn = 128 , Q.Matm = 128;
//    canPush(3 , 127);
    mycnt.clear();
//    cnt(3 , 127);
//    sort(ALL(mycnt));
//    printf("%d\n" , unique(ALL(mycnt)) - mycnt.begin());
////    return;
//    for (int i = 0 ; i < 128 ; ++i)
//        for (int j = 0 ; j < 128; ++j)
//            canPush(i , j);
    for (int i = 0 ; i < 128 ; ++i)
        for (int j = 0 ; j < 128 ; ++j){
            if (canPush(127 - j , i)){
                mycnt.clear();
                cnt(127 - j , i);

                sort( ALL(mycnt) );
                Q.a[j][i] = unique(ALL(mycnt)) - mycnt.begin();
//
//                printf("<<<<<<<<<<<\n");
//                temp.hash = j;printf("%d:\n" , j);temp.decode();temp.output();
//                temp.hash = i;printf("%d:\n" , i);temp.decode();temp.output();
//                printf(">>>>>>>>>>>\n");
//                printf("%d\n" , SZ(mycnt));
//                for (int ds = 0 ; ds < SZ(mycnt) ; ++ds){
//                    for (int Meng = 0 ; Meng < mycnt[ds].del.size() ; ++Meng)
//                        printf("(%d,%d)  " , mycnt[ds].del[Meng].fi , mycnt[ds].del[Meng].se);
//                    cout << endl;
//                }
//                cout << endl;
//                printf("%d\n" , Q.a[j][i]);
            }
            else Q.a[j][i] = 0;
        }
}
void initialR(){
    R.init(Q);
}
void init(){
    memset(ok , -1 , sizeof(ok));
    for (int i = 0 ; i < 128 ; ++i)
        for (int j = 0 ; j < 128 ; ++j)
            memory[i][j].clear();
    initialP();
    initialQ();
    initialR();
//    cout << "GG" << endl;
}
int main(){
//    freopen("0.in" , "r" , stdin);
//    freopen("1.out" , "w" , stdout);
    init();
    solve();
}


XLK的代码:
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<vector>
using namespace std;
#define fr(i,n) for(int i=0;i<n;i++)
#define fo(i,n) for(int i=1;i<=n;i++)
#define fe(i,n) for(__typeof(n.begin()) i=n.begin();i!=n.end();i++)
int a[100020],ac;
int v[100020];
long long A[130][130];
long long B[130][130];
int N=1<<7,p=1000000007;
int mk(int x,int y,int z)
{
    return 1<<x|1<<y|1<<z;
}
void pre()
{
    int x[]={0,0,1,1,1,2,2};
    int y[]={1,2,0,1,2,0,1};
    int r[3][3]={-1,0,1,2,3,4,5,6,-1};
    int u[3][3]={-1,7,8,9,10,11,12,13,-1};
    int dx[]={1,0,-1,0};
    int dy[]={0,1,0,-1};
    for(int i=0;i<7;i++)
    {
        int nx=x[i],ny=y[i];
        for(int i=0;i<4;i++)
        {
            int qx=nx+dx[i];
            int qy=ny+dy[i];
            if(qx>=0&&qy>=0&&qx<3&&qy<3&&r[qx][qy]!=-1)
            {
                a[ac++]=mk(r[nx][ny],u[nx][ny],r[qx][qy]);
                a[ac++]=mk(r[nx][ny],u[nx][ny],u[qx][qy]);
            }
            int px=nx+dx[i+1&3];
            int py=ny+dy[i+1&3];
            if(qx>=0&&qy>=0&&qx<3&&qy<3&&r[qx][qy]!=-1)
                if(px>=0&&py>=0&&px<3&&py<3&&r[px][py]!=-1)
                {
                    a[ac++]=mk(r[nx][ny],r[px][py],r[qx][qy]);
//                  a[ac++]=mk(u[nx][ny],u[px][py],u[qx][qy]);
                }                   
        }
    }
}
void mul(long long a[130][130],long long b[130][130],long long c[130][130])
{
    long long r[130][130]={};
    for(int i=0;i<N;i++)
        for(int k=0;k<N;k++)
            if(a[i][k])
                for(int j=0;j<N;j++)
                    r[i][j]=(r[i][j]+a[i][k]*b[k][j])%p;
    for(int i=0;i<N;i++)
        for(int j=0;j<N;j++)
            c[i][j]=r[i][j];
}
int main()
{
    N++; 
    pre();
//  cout << ac << endl;
    v[0]=1;
    for(int j=0;j<ac;j++)
        for(int i=0;i<1<<14;i++)
            if(v[i])
                if((i&a[j])==0)
                    v[i|a[j]]++;
    int t,n;
    for(;~scanf("%d",&n);)
    {
        memset(A,0,sizeof A);
        memset(B,0,sizeof B);
        A[0][0]=1;
        for(int i=0;i<N-1;i++)
            for(int j=0;j<N-1;j++)
                B[i][j]=v[i<<7|(127^j)];
        n++;
        int w=0;
        for(int i=0;i<7;i++)
        {
            int d;
            scanf("%1d",&d);
            w=w*2+1-d;
        }
        B[w][N-1]=1;
        B[N-1][N-1]=1;
        for(;n;n>>=1)
        {
            if(n&1)
                mul(A,B,A);
            mul(B,B,B);
        }
        if(A[0][N-1]==0)
            puts("No way");
        else
            printf("%d\n",(int)A[0][N-1]);
    }
    return 0;
}

Krites 的代码:
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <cmath>
  
using namespace std;
  
#ifndef ONLINE_JUDGE
#define DEBUG(a) cout << #a"= " << a << endl
#else
#define DEBUG(a)
#endif
typedef long long LL;
const int maxn = 1 << 7;
const int mod = (int)1e9 + 7;
 
struct Martix {
    LL C[maxn][maxn];
    Martix() { memset(C, 0, sizeof(C)); }
    void init() { memset(C, 0, sizeof(C)); }
    void initC() { for (int i = 0; i < maxn; ++i) C[i][i] = 1; }
    Martix operator*(const Martix& rhs) const {
        Martix res;
        for (int i = 0; i < maxn; ++i) {
            for (int j = 0; j < maxn; ++j) {
                for (int k = 0; k < maxn; ++k) {
                    res.C[i][j] += C[i][k] * rhs.C[k][j];
                    res.C[i][j] %= mod;
                }
            }
        }
        return res;
    }
    Martix operator+(const Martix& rhs) const {
        Martix res;
        for (int i = 0; i < maxn; ++i) {
            for (int j = 0; j < maxn; ++j) {
                res.C[i][j] = C[i][j] + rhs.C[i][j];
                if (res.C[i][j] >= mod) res.C[i][j] -= mod;
            }
        }
        return res;
    }
};
 
Martix start, inc;
int Kr[8][4] = {
    {3, 9}, {3, 6}, {6, 12}, {9, 12, 24, 72},
    {24, 48}, {48, 96}, {72, 96}
};
int Sr[] = {
    7, 11, 13, 14, 25, 56, 76, 88, 104, 112
};
void dfs(int deep, int s, int ps) {
    if (deep == 17) {
        ++start.C[ps^(maxn - 1)][s ^ (maxn - 1)]; return;
    }
    if (deep < 7) {
        int sz = (deep == 3) ? 4 : 2;
        for (int i = 0; i < sz; ++i) {
            if ((s & Kr[deep][i]) == Kr[deep][i])
                dfs(deep + 1, s ^ Kr[deep][i], ps ^ (1 << deep));
        }
        dfs(deep + 1, s, ps);
    } else {
        if ((s & Sr[deep - 7]) == Sr[deep - 7]) 
            dfs(deep + 1, s ^ Sr[deep - 7], ps);
        dfs(deep + 1, s, ps);
    }
}
 
Martix powMartix(Martix base, int N) {
    Martix res; res.initC();
    while (N) {
        if (N & 1) res = res * base;
        base = base * base;
        N >>= 1;
    }
    return res;
}
 
Martix sumMartix(int N) {
    if (N == 0) {
        return inc;
    } else if (N == 1) {
        return start;
    } else if (N % 2 == 0) {
        Martix tmp = powMartix(start, N >> 1);
        tmp = tmp + inc;
        return tmp * sumMartix(N >> 1);
    } else {
        Martix tmp = powMartix(start, N);
        return tmp + sumMartix(N - 1);
    }
}
 
void solved(int nT) {
    char s[12]; int N;
    scanf("%d", &N);
    int rs = 0;
    scanf("%s", s);
    if (s[0] == '1') rs |= 1;
    if (s[1] == '1') rs |= 2;
    scanf("%s", s);
    if (s[0] == '1') rs |= 16;
    if (s[1] == '1') rs |= 8;
    if (s[2] == '1') rs |= 4;
    scanf("%s", s);
    if (s[0] == '1') rs |= 32;
    if (s[1] == '1') rs |= 64;
    Martix result = sumMartix(N);
    LL res = result.C[maxn - 1][rs];
    if (res == 0) puts("No way");
    else printf("%lld\n", res);
}
  
int main() {
    dfs(0, maxn - 1, 0);
    inc.initC();
    int T = 1;
    //scanf("%d", &T);
    for (int nT = 1; nT <= T; ++nT) {
        solved(nT);
    }
    return 0;
}

BSBandme 的代码:
#include <iostream>
#include <fstream>
#include <string.h>
#include <cstdio>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <cassert>
#include <iomanip>
#include <math.h>
#include <deque>
#include <utility>
#include <map>
#include <set>
#include <bitset>
#include <numeric>
#include <climits>
#include <cctype>
#include <cmath>
#include <cstdlib>
#include <sstream>
 
using namespace std;
 
typedef unsigned long long ull;
typedef long long ll;
typedef pair <int, int> pii;
typedef pair <ll, ll> pll;
typedef pair <double, double> pdd;
typedef vector <int> vi;
typedef vector <ll> vl;
typedef vector <double> vd;
typedef vector <string> vs;
typedef map <string, int> mpsi;
typedef map <double, int> mpdi;
typedef map <int, int> mpii;
 
const double pi = acos(0.0) * 2.0;
const double eps = 1e-12;
const int step[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
 
template <class T> inline T abs1(T a) {return a < 0 ? -a : a;}
template <class T> inline T max1(T a, T b) {return a > b ? a : b;}
template <class T> inline T min1(T a, T b) {return a < b ? a : b;}
template <class T> inline T gcd1(T a, T b) {
    if(a < b) swap(a, b);
    if(a % b == 0) return b;
    return gcd1(b, a % b);
}
template <class T> inline T lb(T num) {return num & (-num); }
inline int jud(double a, double b){
    if(abs1(a - b) < eps) return 0;
    if(a < b) return -1;
    return 1;
}
template <class t>
inline int find(int val, t *a, int na, bool f_small = 1, bool f_lb = 1){
    if(na == 1) return 0;
    int be = 0, en = na - 1;
    if(a[0] <= a[na - 1]){
        if(f_lb == 0) while(be < en){
            int mid = (be + en + 1) / 2;
            if(jud(a[mid], val) != 1) be = mid;
            else en = mid - 1;
        }else while(be < en){
            int mid = (be + en) / 2;
            if(jud(a[mid], val) != -1) en = mid;
            else be = mid + 1;
        }
        if(f_small && a[be] > val && be != 0) be--;
        if(!f_small && a[be] < val && be != na - 1) be++;
    } else {
        if(f_lb) while(be < en){
            int mid = (be + en + 1) / 2;
            if(jud(a[mid], val) != -1) be = mid;
            else en = mid - 1;
        }else while(be < en){
            int mid = (be + en) / 2;
            if(jud(a[mid], val) != 1) en = mid;
            else be = mid + 1;
        }
        if(!f_small && a[be] < val && be != 0) be--;
        if(f_small && a[be] > val && be != na - 1) be++;
    }
    return be;
}
inline int bitnum(ull nValue){
    nValue = ((0xaaaaaaaaaaaaaaaaull & nValue)>>1) + (0x5555555555555555ull & nValue);
    nValue = ((0xccccccccccccccccull & nValue)>>2) + (0x3333333333333333ull & nValue);
    nValue = ((0xf0f0f0f0f0f0f0f0ull & nValue)>>4) + (0x0f0f0f0f0f0f0f0full & nValue);
    nValue = ((0xff00ff00ff00ff00ull & nValue)>>8) + (0x00ff00ff00ff00ffull & nValue);
    nValue = ((0xffff0000ffff0000ull & nValue)>>16) + (0x0000ffff0000ffffull & nValue);
    nValue = ((0xffffffff00000000ull & nValue)>>32) + (0x00000000ffffffffull & nValue);
    return nValue;
}
long long pow(long long n, long long m, long long mod = 0){
    long long ans = 1;
    long long k = n;
    while(m){
        if(m & 1) {
            ans *= k;
            if(mod) ans %= mod;
        }
        k *= k;
        if(mod) k %= mod;
        m >>= 1;
    }
    return ans;
}
 
const int mod = 1000000007;
template <typename t> struct matrix{
    const static int maxn = 130;
    int row, col;
    t mat[maxn][maxn];
 
    matrix(int r = 0, int c = 0){
        row = r; col = c;
        for(int i = 0; i < row; i++) for(int j = 0; j < col; j++) mat[i][j] = 0;
    }
    bool danweiju(){
        if(row != col) return 0;
        for(int i = 0; i < row; i++) for(int j = 0; j < col; j++) mat[i][j] = bool (i == j);
        return 1;
    }
    matrix operator * (const matrix& b) const{
        int i, j, k;
        matrix <t> c(row, b.col);
        memset(c.mat, 0, sizeof(c.mat));
        for (i = 0; i < c.row; i++) for (k = 0; k < col; k++)
            if(mat[i][k])
                for (j = 0; j < c.col; j++){
                    c.mat[i][j] += mat[i][k] * b.mat[k][j];
                    c.mat[i][j] %= mod;
                }
        return c;
    }
    matrix operator + (const matrix& b) const{
        matrix <t> c(max1(row, b.row), max1(col, b.col));
        for(int i = 0; i < c.row; i++) for(int j = 0; j < c.col; j++){
            t a = 0; if(i < row && j < col) a = mat[i][j];
            t b1 = 0; if(i < b.row && j < b.col) b1 = b.mat[i][j];
            c.mat[i][j] = a + b1;
            c.mat[i][j] %= mod;
        }
        return c;
    }
    matrix operator - (const matrix& b) const{
        matrix <t> c(max1(row, b.row), max1(col, b.col));
        for(int i = 0; i < c.row; i++) for(int j = 0; j < c.col; j++){
            t a = 0; if(i < row && j < col) a = mat[i][j];
            t b1 = 0; if(i < b.row && j < b.col) b1 = b.mat[i][j];
            c.mat[i][j] = a - b1;
        }
        return c;
    }
    inline void operator = (const matrix & b){
        memcpy(mat, b.mat, sizeof(mat));
        col = b.col;  row = b.row;
    }
    matrix pow(int n){
        matrix <t> ans(row, col), temp = *this;
 
        ans.danweiju();
        while(n){
            if(n & 1) ans = ans * temp;
            temp = temp * temp;
            n >>= 1;
        }
        return ans;
    }
    int inv(){
        int i, j, k, is[maxn], js[maxn];
        double t1;
 
        if (row != col) return 0;
        for(k = 0; k < row; k++){
            for(t1 = 0,i = k; i < row; i++) for(j = k; j < row; j++)
                if(fabs(mat[i][j]) > t1)
                    t1=fabs(mat[is[k] = i][js[k] = j]);
            if (fabs(t1 - 0) < 1e-9) return 0;
            if (is[k] != k) for(j = 0; j < row; j++)
                t1 = mat[k][j], mat[k][j] = mat[is[k]][j], mat[is[k]][j] = t1;
            if (js[k] != k) for (i = 0; i < row; i++)
                t1 = mat[i][k], mat[i][k] = mat[i][js[k]], mat[i][js[k]] = t1;
            mat[k][k] = 1 / mat[k][k];
            for(j = 0; j < row; j++) if (j != k)
                mat[k][j] *= mat[k][k];
            for (i = 0; i < row; i++)    if (i != k)
                for (j = 0; j < row; j++) if (j != k)
                    mat[i][j] -= mat[i][k] * mat[k][j];
            for (i = 0;i < row; i++) if (i != k)
                mat[i][k] *= -mat[k][k];
        }
        for (k = row-1; k >= 0; k--){
            for (j = 0; j < row; j++) if (js[k] != k)
                    t1 = mat[k][j], mat[k][j] = mat[js[k]][j], mat[js[k]][j]=t1;
            for (i = 0; i < row; i++) if (is[k] != k)
                t1 = mat[i][k], mat[i][k] = mat[i][is[k]], mat[i][is[k]] = t1;
        }
        return 1;
    }
    double det(){
        int i, j, k, sign = 0;
        double b[maxn][maxn], ret = 1, t1;
 
        if (row != col) return 0;
        for (i = 0; i < row; i++) for (j = 0; j < col; j++)
            b[i][j] = mat[i][j];
        for (i = 0; i < row; i++){
            if (fabs(b[i][i] - 0) < 1e-9){
                for (j = i + 1; j < row; j++)
                    if (fabs(b[j][i] - 0) > 1e-9) break;
                    if (j == row) return 0;
                    for (k = i; k < row; k++)
                        t1 = b[i][k], b[i][k] = b[j][k], b[j][k] = t1;
                    sign++;
            }
            ret *= b[i][i];
            for (k = i + 1; k < row; k++) b[i][k] /= b[i][i];
            for (j = i + 1; j < row; j++) for (k = i + 1; k < row; k++)
                b[j][k] -= b[j][i] * b[i][k];
        }
        if (sign & 1) ret = -ret;
        return ret;
    }
};
 
const int trans[42][2] = {{1, 3}, {1, 9}, {2, 3}, {2, 18}, {4, 12}, {4, 36}, {8, 12}, {8, 72}, {8, 9}, {8, 24}, {16, 24}, {16, 18}, {32, 36}, {32, 96}, {64, 96}, {64, 72},
                            {3, 1}, {3, 2}, {12, 4}, {12, 8}, {24, 8}, {24, 16}, {96, 32}, {96, 64}, {36, 4}, {36, 32}, {9, 1}, {9, 8}, {72, 8}, {72, 64}, {18, 2}, {18, 16}
                            , {11, 0}, {19, 0}, {13, 0}, {44, 0}, {76, 0}, {25, 0}, {26, 0}, {88, 0}, {100, 0}, {104, 0}};
vi wh[100];
ll dp[128][128];
bool f[128][128];
pii q[1 << 15];
int lq, rq;
int ncase, n;
char str[10];
matrix <ll> m(128, 128);
 
int main(){
    for(int i = 0; i < 42; i++){
        int k = lb(trans[i][0]);
        wh[k].push_back(i);
    }
    for(int i = 0; i < 128; i++){
        memset(dp, 0, sizeof(dp));
        memset(f, 0, sizeof(f));
        dp[i][0] = 1; rq = 1; f[i][0] = 1;
        q[lq = 0] = make_pair(i, 0);
        for(; rq != lq; ){
            int wh1 = lb(q[lq].first + 1);
            for(int j = 0; j < (int)wh[wh1].size(); j++){
                if((q[lq].first & trans[wh[wh1][j]][0]) || (q[lq].second & trans[wh[wh1][j]][1])) continue;
                pii p;
                p.first = q[lq].first | trans[wh[wh1][j]][0];
                p.second = q[lq].second | trans[wh[wh1][j]][1];
                dp[p.first][p.second] += dp[q[lq].first][q[lq].second];
                if(p.first != 127 && f[p.first][p.second] == 0){
                    f[p.first][p.second] = 1;
                    q[rq++] = p;
                }
            }
            lq++;
        }
        for(int j = 0; j < 128; j++) m.mat[i][j] = dp[127][j];
    }
 
    while(scanf("%d", &n) != -1){
        for(int i = 0; i < 7; i++)
            while(str[i] != 48 && str[i] != 49)
                scanf("%c", str + i);
 
        int num = 0;
        for(int i = 0; i < 7; i++) num += (str[i] - 48) << i;
 
        m = m.pow(n - 1);
        ll ans = m.mat[0][num];
        for(int i = 0; i < 127; i++){
            for(int j = 32; j < 42; j++)
                if(((i & trans[j][0]) == 0) && ((i | trans[j][0]) == num)){
                    ans += m.mat[0][i];
                    break;
                }
        }
        if(num == 127) ans += m.mat[0][2] + m.mat[0][8] + m.mat[0][32];
        cout << num << ' ' << ans % mod << endl;
    }
 
    return 0;
}


总结:
总之我还是太弱了啊T_T。
XLK 好强啊T_T
孟竹祝你寒假快乐~love you
祝大家寒假开心,新春快乐













你可能感兴趣的:(Contest - ACdream原创群赛の妹子的假期生活 解题报告)