[2018.07.12 T3] B君的第三题

暂无链接

B君的第三题

【问题描述】

日光之下,并无新事。

大家还记得BZOJ1494[NOI2007]生成树计数吗?这个题目就是原版环形的生成树计数。

考虑到有些同学没有看过这个题目,我们简述这个题目如下。

输入 k , n ( n 2 k + 1 ) ,考虑 n 个点围成一个环,所有距离 k 的点对之间有一条无向边。

相邻的 2 个点距离为 1 ,如果两个点之间有 d 个点,他们的距离为 d + 1

问这个图生成树的个数,结果对 65521 取模。

【输入格式】

输入包含 2 个整数 k , n

【输出格式】

一行一个整数,表示答案。

【输入样例】

2 8

【输出样例】

3528

【数据范围】

对于 100 % 的数据,满足 1 k 5 , 2 k + 1 n 10 15

部分分和原题一样,一共有 20 组数据。

对于 1 4 号部分分, n 的范围改为 n 12

数据非常有梯度。

题解

前一天讲了这道题的玄妙做法,没想到第二天就 T M O ( n ! n 2 ) 暴力算行列式的程序不知道哪里取膜又炸了, 15 分滚粗。。。

玄学做法的原理大概是因为 k 一定时,答案是一个关于 n 的递推数列,我们先用优美的 O ( n 3 ) 爆算前几项的值,再用高斯消元把递推数列的系数解出来。对于 1 k 5 每个都打一个递推数列系数以及前几项的表,算的时候再矩阵加速递推得到答案。

贴上毕克的题解:

无标题.png

我有生之年争取写一下这道题,先贴个标算吧。

代码
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const ll mod=65521;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
// head

namespace linear_seq {
    const int N=10010;
    ll res[N],base[N],_c[N],_md[N];

    vector<int> Md;
    void mul(ll *a,ll *b,int k) {
        rep(i,0,k+k) _c[i]=0;
        rep(i,0,k) if (a[i]) rep(j,0,k) _c[i+j]=(_c[i+j]+a[i]*b[j])%mod;
        for (int i=k+k-1;i>=k;i--) if (_c[i])
            rep(j,0,SZ(Md)) _c[i-k+Md[j]]=(_c[i-k+Md[j]]-_c[i]*_md[Md[j]])%mod;
        rep(i,0,k) a[i]=_c[i];
    }
    int solve(ll n,VI a,VI b) { // a 系数 b 初值 b[n+1]=a[0]*b[n]+...
//        printf("%d\n",SZ(b));
        ll ans=0,pnt=0;
        int k=SZ(a);
        assert(SZ(a)==SZ(b));
        rep(i,0,k) _md[k-1-i]=-a[i];_md[k]=1;
        Md.clear();
        rep(i,0,k) if (_md[i]!=0) Md.push_back(i);
        rep(i,0,k) res[i]=base[i]=0;
        res[0]=1;
        while ((1ll<<pnt)<=n) pnt++;
        for (int p=pnt;p>=0;p--) {
            mul(res,res,k);
            if ((n>>p)&1) {
                for (int i=k-1;i>=0;i--) res[i+1]=res[i];res[0]=0;
                rep(j,0,SZ(Md)) res[Md[j]]=(res[Md[j]]-res[k]*_md[Md[j]])%mod;
            }
        }
        rep(i,0,k) ans=(ans+res[i]*b[i])%mod;
        if (ans<0) ans+=mod;
        return ans;
    }
    VI BM(VI s) {
        VI C(1,1),B(1,1);
        int L=0,m=1,b=1;
        rep(n,0,SZ(s)) {
            ll d=0;
            rep(i,0,L+1) d=(d+(ll)C[i]*s[n-i])%mod;
            if (d==0) ++m;
            else if (2*L<=n) {
                VI T=C;
                ll c=mod-d*powmod(b,mod-2)%mod;
                while (SZ(C)<SZ(B)+m) C.pb(0);
                rep(i,0,SZ(B)) C[i+m]=(C[i+m]+c*B[i])%mod;
                L=n+1-L; B=T; b=d; m=1;
            } else {
                ll c=mod-d*powmod(b,mod-2)%mod;
                while (SZ(C)<SZ(B)+m) C.pb(0);
                rep(i,0,SZ(B)) C[i+m]=(C[i+m]+c*B[i])%mod;
                ++m;
            }
        }
        return C;
    }
    int gao(VI a,ll n) {
        VI c=BM(a);
        c.erase(c.begin());
        rep(i,0,SZ(c)) c[i]=(mod-c[i])%mod;
        return solve(n,c,VI(a.begin(),a.begin()+SZ(c)));
    }
};

int a[2020][2020];
long long det(int n) {
    long long ans = 1;
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            while (a[j][i] != 0) {
                int u = a[i][i] / a[j][i];
                for (int k = 0; k < n; k++) {
                    int t = (a[i][k] - (long long)a[j][k] * u % mod + mod) % mod;
                    a[i][k] = a[j][k];
                    a[j][k] = t;
                }
                ans = -ans;
            }
        }
        ans = ans * a[i][i] % mod;
    }
    if (ans < 0) {
        ans += mod;
    }
    return ans;
}

long long work(int k, int n) {
//  assert(n > 2 * k + 1);
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (i == j) {
                a[i][j] = 2 * k;
            } else {
                if (abs(i - j) <= k || n - abs(i - j) <= k) {
                    a[i][j] = -1;
                } else {
                    a[i][j] = 0;
                }
            }
        }
    }
/*
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            printf("%d%c", a[i][j], j == n - 1 ? '\n' : ' ');
        }
    }
*/
    return det(n - 1);
}



// 1 2
// 2 6
// 3 18
// 4 54
// 5 162
// 6 486
vector<int> b[6] = {
{
}
,
{
3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350}
,
{
125,384,1183,3528,10404,30250,21610,52269,50547,24176,12215,58227,47572,21494,8510,41651,41315,15658,12131,41046,34656,9881,43507,56897,18747,65101,23907,6784,18854,51000,50212,42835,57695,59376,59821,8745,20995,1320,32118,32909,28074,62914,37893,63505,52003,39511,8660,61915,3156,5010,31099,22444,16592,33692,58254,55440,9038,21704,43718,21732,33394,4713,10352,57199,28313,56055,30814,7863,16951,12280,35355,39111,34282,40082,63471,40204,12127,35983,64501,22931,25802,56191,61738,14390,47041,44187,35247,57902,47644,11880,56854,44340,58358,59650,57160,57159,14726,4001,17782,27337,44251,929,59229,58096,52576,29765,21733,59243,46956,57181,30383,36744,52489,34707,18677,7295,60787,33027,14455,14119,64314,20954,13947,27130,6522,64234,5138,55687,2586,23443,49400,62537,36765,843,58877,42015,32773,19971,19467,50324,45248,9878,42030,35621,28970,22811,56903,30633,60397,14901,12111,42401,20702,41611,3725,37986,24369,35112,37372,10129,34178,19045,25448,5430,30977,61532,37267,53087,51947,19117,22833,52524,62965,47189,15642,29301,29140,28434,12038,34215,19603,45291,54652,42296,37659,41439,35399,3844,43123,57884,59109,36405,5404,57821,55647,19495,44928,1579,37246,61034,54116,4221,23142,26418,8268,22603,51084,13440,41302,54148,33294,32931,51567,25096,11885,4024,60129,32919,9211,47687,62332,584,55660,61892,30139,27681,21497,6654,7235,3676,28749,35432,44566,44102,26120,32224,62939,2346,15549,17352,17682,3728,49921,17193,19830,26612,62790,52253,27264,1930,30455,8207,28708,63648,21936,51596,30924,10961,15852,40348,39667,6727,29474,35757,24735,53562,40482,25747,8527,20076,12347,6963,20640,32972,2993,31447,8136,12690,44101,8523,29987,7640,53475,12223,28004,16296,9048,27933,9710,48153,15983,52249,26713,23450,16296,10396,97,23073,55419,356,58066,61192,5798,34261,60818,24074,5909,32666,21170,38038,57533,17994,12914,52508,30032,52040,25128,30417,60470,58220,41317,2166,47172,52502,33153,30024,21070,4793,12810,51692,49218,57507,38815,37132,29500,6072,30341,55159,7545,4201,49691,42043,54373,23208,9266,15502}
,
{
16807,17423,19038,4069,36749,10890,20559,13383,44811,44978,31152,53478,7585,61903,7694,36892,16182,32848,7007,55636,5469,46229,26724,56247,29546,4511,24057,44025,8060,47158,39698,19408,30892,41606,20256,55010,53423,13200,2650,57980,62663,65109,29251,58552,23859,48161,12137,30015,36255,20680,43330,30778,24317,45099,52169,62139,49783,43612,18362,16488,50535,23224,57527,19611,85,36668,17680,36269,58487,42885,13171,61041,11347,9133,57358,27372,41905,16078,46320,16575,42464,16096,6242,51443,11435,43584,18807,7069,56857,28859,59010,3630,62102,36494,36168,63550,43716,42050,22537,6076,14572,6261,56784,37620,57442,3471,43627,6001,46102,21167,29956,26067,31409,50300,31243,62965,8213,24267,16009,17911,36452,886,55664,35472,10561,32903,36028,7804,39680,30108,56342,13843,51370,24817,57587,35487,1403,5198,38028,41952,24606,13544,40141,47250,44144,64823,30609,13692,33992,46755,44248,27794,5389,24503,50618,38291,38302,7288,51481,42184,50324,58587,52194,52008,57137,50487,62476,1776,60499,50671,44431,34668,61094,54353,363,35312,25424,61536,48493,52614,34146,15560,32219,1869,18126,14452,25597,50693,7472,43594,9330,24268,30,44783,20994,57172,12531,37684,35650,13144,52788,20024,56354,19918,30728,30606,49274,20118,13967,26363,46524,41435,34677,9167,64291,33976,39947,2346,59056,22246,9321,5914,36012,31900,31697,54133,37940,47423,6241,65484,54562,38796,6956,41920,35830,27909,60597,5034,19986,50215,58859,55413,23598,60923,47856,17688,65220,52483,58055,12717,36972,10620,20796,55406,17587,33333,8068,53391,24494,42701,23631,51500,55451,21176,35983,37983,29654,65234,11854,26675,15106,46506,25978,6736,47551,65018,63996,6872,36408,14145,38093,5428,36111,50242,19901,13224,11668,51815,63276,36488,37478,28253,27160,22748,48302,33136,62472,61446,2887,59017,32230,32828,6034,13392,26121,46567,49015,44893,43493,49850,40578,25326,16527,650,2908,29049,25537,38508,3969,50706,3852,64045,61010,36131,56804,61261,60507,47081,23548,29574,26335,29275,65318,45470,15851,29673,65074,36355,35575,12464,10451,13438,49532,3191}
,
{
65457,7500,44205,40188,48640,8405,785,15584,27550,24009,2806,39941,39586,12655,29060,63519,440,55231,44413,1719,61638,15338,1980,42275,50263,4780,56562,5966,13459,65345,34985,7721,23101,124,14839,52885,15175,36581,16396,48404,48035,17828,33918,65101,15000,2860,2388,63410,9605,50082,55806,49163,56598,63631,33389,36239,18509,40669,29987,46422,39166,40016,15570,36100,19816,37187,48986,14371,51476,10577,61604,15072,24301,47010,5509,28989,4735,1016,60393,38076,3973,47962,16682,32195,16845,29563,30593,3200,55581,53444,10781,15159,24463,18683,63189,6104,15064,60939,5108,30884,48522,53159,51448,44802,25255,1343,54461,22264,14980,30703,40698,30641,4721,7627,59840,29277,53858,41849,52942,26753,56814,23701,5161,3751,62001,59067,31328,1084,30477,61543,45881,62054,20007,45929,19401,26878,26350,52803,43797,64858,61082,12338,31973,33090,33956,21810,34544,4190,57560,52715,49263,50204,3810,26041,31447,28808,23333,20852,2756,31564,48059,60218,45370,30574,48177,52248,43554,38500,12166,10641,50777,59791,51809,50995,64207,28953,5581,21038,57162,11022,30276,54219,26944,7399,22210,13095,17120,35734,45435,4560,49186,45344,56123,38237,37488,60423,28033,54803,13668,8795,15496,3902,4124,25298,5110,4494,51292,60047,28359,7284,1203,1339,22987,55154,522,8231,30822,20862,49824,49658,13354,38910,44832,2054,19735,39762,61153,14271,45108,44050,28307,9848,29857,8527,64350,41904,56414,53960,3331,3459,63050,34136,16937,27257,6294,5475,22606,24897,2173,48705,20363,32092,52402,32423,43837,62663,34074,15305,53041,61291,50562,42886,7378,32542,25285,40285,30798,51419,37122,30142,26126,20053,34345,48811,22117,52152,59108,6776,12783,32711,51801,22879,61557,52173,40812,40738,43087,3316,53122,19760,29890,22240,15875,24059,57464,23249,27419,20660,35047,59415,6544,17349,39171,30457,30593,63362,26676,3636,587,27475,15418,41971,49618,35009,34379,1227,6238,19074,13466,57044,62040,40019,63370,17499,19823,39565,9190,41949,25895,10107,51768,46180,54805,39548,23277,61967,36479,62306,10039,6415,58709,27498}
,
{
43464,44962,35706,26874,2031,35703,14530,53646,61395,56708,29157,43858,3788,7056,41580,35556,22057,12105,25313,43903,43174,50192,48518,28112,37197,16270,49973,27582,18340,39356,28374,39671,33552,22814,29972,42427,19919,38723,24057,51493,6507,45387,18936,65511,31659,44915,62932,34532,65492,5505,65280,61430,9555,21382,18222,21311,853,52691,17163,48026,45847,22611,22383,30878,32423,7502,14151,47992,49564,36686,24946,21597,5702,10921,28206,39980,64500,34046,44791,42032,19696,32425,58579,50204,11055,40170,56738,14539,3621,56024,40757,56759,1895,3710,15280,40381,27494,42590,45942,46226,4201,64024,26768,41146,2839,57415,45261,18437,19547,34769,5118,1282,62750,31296,62980,42068,57199,26653,51220,13640,60680,16245,27774,54000,14218,38367,56167,56929,61021,33773,62448,58886,2385,24829,45945,46912,21640,18358,36563,28022,33944,42920,38354,47928,52596,36132,28846,50297,46818,25798,48043,58726,47491,31838,56042,32772,22166,49864,13935,19648,521,63481,2020,38638,35612,42103,18176,51317,36874,63761,54291,47966,13735,34283,57328,15342,31700,9304,61996,13174,58295,39455,43873,6530,38902,28841,48576,64348,47329,9533,17733,38313,31869,19978,20775,50463,14683,13131,29902,351,19925,2860,5112,21389,58902,62380,56670,32690,1501,30082,16172,56527,50661,48473,51934,18084,59554,19668,31400,18454,18680,28997,61623,48579,4333,31229,34275,46430,49785,39399,54582,26873,2452,13904,6074,46467,59233,43350,55145,35635,52365,57841,29069,12377,44369,17612,25777,48302,31610,16214,15544,61155,27005,10047,22468,10078,63,46700,57796,9975,65036,47084,25347,42901,13408,4053,21478,62435,17113,22335,25616,31491,11966,2324,40677,50513,59141,26694,31792,1981,47464,30649,47932,36074,20166,47925,13523,29003,41595,13616,40375,2403,43249,62366,56838,31673,4701,45182,36767,19189,5139,6231,19837,62091,5389,61964,34115,38052,21934,35726,1092,22352,43179,6470,52404,30237,10894,6979,65507,5340,6574,11305,34844,52652,56587,35647,19369,51708,19947,51016,56199,65076,6145,34106,40143,28724,27128,36157,26644,63840}
};
void maketable() {
    printf("{\n");
    for (int k = 1; k <= 5; k++) {
        if (k > 1) {
            printf(",\n");
        }
        printf("{\n");
        for (int i = 2 * k + 1; i <= 350; i++) {
            if (i > 2 * k + 1) {
                printf(",");
            }
            printf("%lld", work(k, i));
        }
        printf("}\n");
    }
    printf("}\n");
}
int main() {
    freopen("shanghai.in","r",stdin);
    freopen("shanghai.out","w",stdout);
    int k;
    long long n;
//  maketable();
//  k = 5;
    cin >> k >> n;
//  vector<int> a;
//  for (int i = 2 * k + 1; i <= 350; i++) {
//      a.push_back(work(k, i));
//  }
    cout << linear_seq::gao(b[k], n - (2 * k + 1)) << endl;
//  cout << linear_seq::gao(a, n - (2 * k + 1)) << endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/shadypi/article/details/81031496
今日推荐