杂题

NOI2013

向量内积

很有奥妙的题。暴力分很多,直接枚举有60,加个random_shuflle优化一下就有70了。

把n个向量写在一起变成一个n*d的矩阵,这个矩阵乘它的转置得到的矩阵第i行第j列就是第i个向量和第j个向量的内积,把这个矩阵跟全1矩阵比较即可知道有无解。

这样是个暴力的复杂度,用一些玄学的方式优化一下,随机一个n维向量和两个矩阵相乘,再比较。为了提高正确性要多随机几次。

这是mod2的情况下,mod3的情况下因为结果为0,1,2不能和全1矩阵比较,发现2^2=1^2=1(mod 3),那么把结果平方再比较。化化式子发现相当于每个向量变成d^2维的向量,bi*j=ai*aj。

矩阵游戏

暴力十进制矩阵快速幂,卡卡常说不定就过了。

更优美的做法,大力推一波式子,加等比数列求和加欧拉定理加快速幂就差不多了。

 

thupc2018

太菜了网络赛只写了几道签到题,签到题都不会写没写完,要是以后改了再来补。

 

一直想写没写的几道题:

2961: 共点圆

cdq维护凸包,也是当时觉得好难啊。其实蛮好写的。至少比splay好写多了,但若是要强制在线我也没什么办法啊。

View Code

 

agc

001_d

读题读了好久,好久,好久。。。

相同的位置连边,要使得最后图联通,画图发现奇数的回文串只能伸出去一边,偶数的可以伸出去两边或一边,奇数的只能放两端,偶数的可以放中间或两端。

 

001_e

$ans=\sum_{i=1}^n\sum_{j=1}^{i-1}C(a_j+a_i+b_j+b_i,a_j+a_i)$

即网格图上从$(-a_i,-b-i)$,到$(a_j,b_j)$的方案数

把所有i一起dp,减去从i到i的再除以2即可。

 

001_f

长沙做过的原题我都不会,,真真是菜得没话说。。

原序列为a,设p[a[i]]=i,问题转换为使p数组字典序最小。操作转换为相邻两项的值的差的绝对值大于k即可交换。每个数向它后面不能交换的连边,即它们的先后顺序定下来了,再拓扑排序即可。发现这样会有多余的边。每个数只会向(a-k,a),(a,a+k),线段树维护区间位置最小值,每个数向后面第一个不能交换的连边即可。

 

002_d

sxy出过的题,似乎被我暴力搞过了。传送门

 

002_e

我根本一点都不懂博弈啊。

llj说因为子游戏之间有影响所以不能直接用nim积算sg函数。

题解好奥妙啊。这个博主写得草鸡好啊,图画的简直良心。

 1     //Achen
 2     #include<algorithm>
 3     #include<iostream>
 4     #include<cstring>
 5     #include<cstdlib>
 6     #include<vector>
 7     #include<cstdio>
 8     #include<queue>
 9     #include<cmath>
10     #include<set>
11     #include<map>
12     #define For(i,a,b) for(int i=(a);i<=(b);i++)
13     #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
14     const int N=1e5+7;
15     typedef long long LL;
16     typedef double db;
17     using namespace std;
18     int n,a[N],fl1,fl2,sum;
19      
20     template<typename T> void read(T &x) {
21     char ch=getchar(); x=0; T f=1;
22     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
23     if(ch=='-') f=-1,ch=getchar();
24     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
25     }
26      
27     bool cmp(const int &A,const int &B) {
28     return A>B;
29     }
30      
31     //#define DEBUG
32     int main() {
33     #ifdef DEBUG
34     freopen("1.in","r",stdin);
35     //freopen(".out","w",stdout);
36     #endif
37     read(n);
38     For(i,1,n) read(a[i]);
39     sort(a+1,a+n+1,cmp);
40     For(i,1,n) {
41     if(a[i+1]<i+1) {
42     i--;
43     int j=i; while(a[j+1]>i) j++;
44     if(((a[i+1]-i)&1)&&((j-i)&1)) puts("Second");
45     else puts("First");
46     break;
47     }
48     }
49     return 0;
50     }
View Code

 

002_f

 这题就更加奥妙重重了。。还是刚才那个博主,写得特别好。

 1     //Achen
 2     #include<algorithm>
 3     #include<iostream>
 4     #include<cstring>
 5     #include<cstdlib>
 6     #include<vector>
 7     #include<cstdio>
 8     #include<queue>
 9     #include<cmath>
10     #include<set>
11     #include<map>
12     #define For(i,a,b) for(int i=(a);i<=(b);i++)
13     #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
14     const int N=2007,mod=1e9+7;
15     typedef long long LL;
16     typedef double db;
17     using namespace std;
18     int n,k;
19     LL dp[N][N],fac[N*N],inv[N*N];
20      
21     template<typename T> void read(T &x) {
22     char ch=getchar(); x=0; T f=1;
23     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
24     if(ch=='-') f=-1,ch=getchar();
25     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
26     }
27      
28     LL C(int n,int m) {
29     if(n<m) return 0;
30     return fac[n]*inv[m]%mod*inv[n-m]%mod;
31     }
32      
33     //#define DEBUG
34     int main() {
35     #ifdef DEBUG
36     freopen("1.in","r",stdin);
37     //freopen(".out","w",stdout);
38     #endif
39     read(n); read(k);
40     fac[0]=inv[0]=inv[1]=1;
41     For(i,1,n*k) fac[i]=fac[i-1]*i%mod;
42     For(i,2,n*k) inv[i]=(mod-mod/i*inv[mod%i]%mod)%mod;
43     For(i,2,n*k) inv[i]=inv[i-1]*inv[i]%mod;
44     if(k==1) {
45     puts("1");
46     return 0;
47     }
48     dp[n][n]=1;
49     Rep(i,n,0) {
50     Rep(j,n,i) {
51     if(i)
52     (dp[i-1][j]+=dp[i][j])%=mod;
53     if(j>i)
54     (dp[i][j-1]+=dp[i][j]*(k>2?C(i+j*(k-1)-1,k-2):1)%mod)%=mod;
55     }
56     }
57     LL ans=dp[0][0]*fac[n]%mod;
58     printf("%lld\n",ans);
59     return 0;
60     }
View Code

 

003_d

题解

//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<queue>
#include<cmath>
#include<set>
#include<map>
#define For(i,a,b) for(int i=(a);i<=(b);i++)
#define Rep(i,a,b) for(int i=(a);i>=(b);i--)
const int N=2e5+7;
typedef long long LL; 
typedef double db;
using namespace std;
int n;
LL s[N],ans;

template<typename T> void read(T &x) {
    char ch=getchar(); x=0; T f=1;
    while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    if(ch=='-') f=-1,ch=getchar();
    for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
}

map<LL,LL>f;
map<LL,LL>g;
map<LL,LL>cnt;

int bo[N],p[N];
void get_prime(int n) {
    For(i,2,n) {
        if(!bo[i]) p[++p[0]]=i;
        for(int j=1;j<=p[0]&&p[j]*i<=n;j++) {
            bo[p[j]*i]=1;
            if(i%p[j]==0) break;
        }
    }
}

void get_it(LL x) {
    if(f[x]) {
        LL z=f[x];
        if(z==-1) ans++;
        else cnt[z]++;
        return;
    }
    LL tp=x,fx=1,gx=1;
    For(i,0,325) {
        if(tp%p[i]==0) {
            int c=0;
            while(tp%p[i]==0) {
                tp/=p[i]; c++;
            } c%=3;
            if(c==1) fx*=p[i],gx*=(LL)p[i]*p[i];
            else if(c==2) fx*=(LL)p[i]*p[i],gx*=p[i];
        }
        if(tp==1) break;
    }
    if(tp!=1) {
        if(tp<=100000&&!bo[tp]) { fx*=tp; gx*=tp*tp; }
        else {
            LL tt=sqrt(tp);
            if(tt*tt==tp) { fx*=tp; gx*=tt; }
            else { fx*=tp; gx*=tp*tp; }
        }
    }
    f[x]=fx; g[fx]=gx; cnt[fx]++;
}

#define IT map<LL,LL>::iterator 

//#define DEBUG
int main() {
#ifdef DEBUG
    freopen("1.in","r",stdin);
    //freopen(".out","w",stdout);
#endif
    read(n);
    get_prime(100000);
    For(i,1,n) read(s[i]);
    For(i,1,n) 
        get_it(s[i]);
    for(IT it=cnt.begin();it!=cnt.end();++it) {
        LL x=it->first,y=it->second;
        if(x==1&&y) ans++;
        if(cnt[g[x]]<y||(cnt[g[x]]==y&&g[x]<x)) ans+=y;
    }
    printf("%lld\n",ans);
    return 0;
}
View Code

 

003_e

题解

 1 //Achen
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<cstring>
 5 #include<cstdlib>
 6 #include<vector>
 7 #include<cstdio>
 8 #include<queue>
 9 #include<cmath>
10 #include<set>
11 #include<map>
12 #define For(i,a,b) for(int i=(a);i<=(b);i++)
13 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
14 const int N=2e5+7;
15 typedef long long LL; 
16 typedef double db;
17 using namespace std;
18 LL n,q;
19 LL a[N],cnt[N],ans[N];
20 
21 template<typename T> void read(T &x) {
22     char ch=getchar(); x=0; T f=1;
23     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
24     if(ch=='-') f=-1,ch=getchar();
25     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
26 }
27 
28 LL sg[N<<2];
29 #define lc x<<1
30 #define rc ((x<<1)|1)
31 #define mid ((l+r)>>1)
32 void build(int x,int l,int r) {
33     if(l==r) { sg[x]=a[l]; return ; }
34     build(lc,l,mid); build(rc,mid+1,r);
35     sg[x]=min(sg[lc],sg[rc]);
36 }
37 
38 LL qry(int x,int l,int r,int ql,int qr,LL v) {
39     if(ql>qr) return 0;
40     if(l>=ql&&r<=qr) {
41         if(sg[x]>v) return 0;
42         if(l==r) return l;
43         if(sg[rc]<=v) return qry(rc,mid+1,r,ql,qr,v);
44         if(sg[lc]<=v) return qry(lc,l,mid,ql,qr,v); 
45     }
46     if(qr<=mid) return qry(lc,l,mid,ql,qr,v);
47     LL rs=qry(rc,mid+1,r,ql,qr,v);
48     if(rs) return rs; else return qry(lc,l,mid,ql,qr,v);    
49 }
50 
51 LL cf[N];
52 void solve(int x,LL l,LL c) {
53     if(!x||!l) {
54         if(!x) cf[l]+=c;
55         return ;
56     }
57     int y=qry(1,1,q,1,x-1,l);
58     cnt[y]+=l/a[y]*c;
59     solve(y,l%a[y],c);
60 }
61 
62 //#define DEBUG
63 int main() {
64 #ifdef DEBUG
65     freopen("1.in","r",stdin);
66     //freopen(".out","w",stdout);
67 #endif
68     read(n); read(q); a[0]=n;
69     if(q==0) {
70         For(i,1,n) puts("1");
71         return 0;
72     }
73     For(i,1,q) read(a[i]);
74     build(1,1,q); cnt[q]=1;
75     Rep(i,q,1) if(cnt[i]) 
76         solve(i,a[i],cnt[i]);
77     ans[n+1]=cnt[0];
78     Rep(i,n,1) ans[i]=ans[i+1]+cf[i];
79     For(i,1,n) printf("%lld\n",ans[i]);
80     return 0;
81 }
View Code

 

003_f

题解

V(k-1):k-1级分形的点数,k级分形中包含2级分形的数量,ev:每个二级分形中的边数

E(k-1):k-1级分形的边数,k级分形中,多少对2级分形间有两边, ud:两个相连二级分形间的边数

//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<queue>
#include<cmath>
#include<set>
#include<map>
#define For(i,a,b) for(int i=(a);i<=(b);i++)
#define Rep(i,a,b) for(int i=(a);i>=(b);i--)
const int N=1007,mod=1e9+7;
typedef long long LL; 
typedef double db;
using namespace std;
LL n,m,k,f[4]={0,0,1,0},g[4],a[N][N],b[N][N],ev,ud,lr,v;
char s[N];

template<typename T> void read(T &x) {
    char ch=getchar(); x=0; T f=1;
    while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    if(ch=='-') f=-1,ch=getchar();
    for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
}

LL ksm(LL a,LL b) {
    LL rs=1,bs=a;
    while(b) {
        if(b&1) rs=rs*bs%mod;
        bs=bs*bs%mod;
        b>>=1;
    }
    return rs;
}

struct jz {
    LL a[4][4];
    friend jz operator *(const jz&A,const jz&B) {
        jz rs;
        For(i,0,3) For(j,0,3) {
            rs.a[i][j]=0;
            For(k,0,3) (rs.a[i][j]+=A.a[i][k]*B.a[k][j]%mod)%=mod;
        }
        return rs;
    }
}bs,rs;

LL jzksm(LL b) {
    while(b) {
        if(b&1) rs=rs*bs;
        bs=bs*bs;
        b>>=1;
    }
}

//#define DEBUG
int main() {
#ifdef DEBUG
    freopen("1.in","r",stdin);
    //freopen(".out","w",stdout);
#endif
    read(n); read(m); read(k);
    For(i,1,n) {
        scanf("%s",s+1);
        For(j,1,m) {
            a[i][j]=(s[j]=='#');
            v+=a[i][j];
        }
    }
    For(i,1,n) lr+=(a[i][1]&a[i][m]);
    For(i,1,m) ud+=(a[1][i]&a[n][i]);
    if(lr&&ud) puts("1");
    else if(!lr&&!ud) printf("%lld\n",ksm(v,k-1));
    else {
        if(lr) {
            For(i,1,n) For(j,1,m) b[j][i]=a[i][j];
            swap(n,m); swap(lr,ud);
        }
        else For(i,1,n) For(j,1,m) b[i][j]=a[i][j];
        For(i,1,n-1) For(j,1,m) if(b[i][j]&&b[i+1][j]) ev++;
        For(i,0,3) rs.a[i][i]=1;
        bs.a[2][0]=1; bs.a[3][1]=1; bs.a[2][2]=v;
        bs.a[2][3]=ev; bs.a[3][3]=ud;
        jzksm(k-1);
        For(i,0,3) For(j,0,3) (g[i]+=f[j]*rs.a[j][i]%mod)%=mod;
        LL ans=(g[2]-g[3]+mod)%mod;
        printf("%lld\n",ans);
    }
    return 0;
}
View Code

 

cf

round456_d

贪心,每次选被r*r的矩形包含最多的点。先把中间的点放进堆,肯定是最优的,每次选了一个点就把它周围四个点放进堆。

 

round456_e

把16个数分成两个集合,每个8个数,爆搜出每个集合1e18内的数的所有数,然后二分答案判断。

 

round457_d

可持久化线段树

 

round457_e

比遥远的国度多了个求lca。

当前根为rt,求u,v的lca,发现lca是lca(u,v),lca(u,rt),lca(v,rt)中和另两个不同的那一个。

 

round458_d

线段树,区间gcd是x的倍数则ok,否则只能有一个数不是x的倍数,递归地找保证只有一个即可。

 

posted @ 2018-05-17 22:26  啊宸  阅读(174)  评论(0编辑  收藏  举报