11月16日——离noip还有3天[学战都市Asterisk]

来源:互联网 发布:js数组去重复的方法 编辑:程序博客网 时间:2024/04/30 23:54

今天吊车尾了……蓝瘦香菇……
于是乎,好好加油……预祝我NOIP不要吊车尾……

每日推荐

今天推荐的是学战都市Asterisk:
作为歌姬党,我就只发歌姬的图吧……好吧,还是发发其他“女主”的图吧……
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
再追加一张歌姬的图!!!
这里写图片描述

小说资源:
http://pan.baidu.com/s/1slaoLtF

开始干正事

LGTB 与序列

LGTB 得到了一个序列,他想在这个序列中选择一个最长的连续子序列,使得这个子序列的最大公约数等于1。请告诉他他能得到的最大长度,如果没有这样的序列,输出-1 。
输入
输入第一行包含一个整数n 代表序列大小
接下来一行,包含n 个整数a1, a2, …, an,代表序列
对于50% 的数据,1 <=n <=1000
对于100% 的数据,1<=n<=10^5,1<=ai<=10^9
输出
输出包含一个整数l,代表最长的连续子序列,如果无解请输出-1

样例
样例输入
2
7 2
样例输出
2
样例输入
3
2 2 4
样例输出
-1

思考

啊啊啊啊啊!!!!!!
我交错程序了!!

题解……

无!!
当序列长度增加的时候,GCD的大小只会变得更小或者不变,那么要求最长的GCD为1(最小)的字串,就是全串。
Ans = GCD==1? N : -1;

code

#include <set>#include <cmath>#include <stack>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <cstdlib>#include <numeric>#include <vector>#include <ctime>#include <queue>#include <list>#include <map>using namespace std;int main(){    freopen("seq.in", "r", stdin);    freopen("seq.out", "w", stdout);    int T,n,g;    scanf("%d%d",&n,&g);    for(int i=1;i<n;i++){        int tmp;        scanf("%d",&tmp);        g=__gcd(g,tmp);//有一个内建函数……    }    if(g!=1)        printf("%d\n",-1);    else printf("%d\n",n);}

LGTB 与桌子

LGTB 新买了一张n  m 的矩(桌) 阵(子),他想给某些1  1 的小矩形染色,使得染色之后,原矩阵的每
个n  n 的子矩阵中都包含恰好k 个被染色了的小矩形
他想知道有多少种染色方案能让他满足上述要求
因为答案可能很大,请输出方案数模1000000007 (109 + 7) 后的值
输入
输入第一行包含三个整数n, m, k 意义如题面所示
对于15% 的数据,1 <= n * m <= 20, n <= m
对于40% 的数据,1 ,= n <= 10, n <= m <= 1000
对于100% 的数据,1 <= n <= 100, n * m  10^18, 0 <= k <= n^2
输出
输出包含1 个整数,代表LGTB 的方案数

样例
样例输入
5 6 1
样例输出
45
样例说明
样例如图所示,如果在灰色区域染一个格子,有20 种方案。如果在两边的白色格子各染一个格子,有25 种
方案。共45 种方案

思路

数学归纳法+快速幂

题解

当前n列有k个染色的时候,假设第1列有x个染色,那么第n+1列也应该有x个染色,后面的同理。
则kn+i列的染色个数与第i列染色个数相同
那么可以分成很多个列长度为n的块同时计算(最后一块小于等于n列)
用dp(i,j)表示处理了所有块的前i列,每一块总的染色个数为j的方案数
Dp(i,j) = ∑dp(i-1,j-p) * (C(n,p)) ^ T[i]
其中T[i]表示m列中共有多少个kn+i列
用快速幂预处理(C(n,p)) ^ T[i]
Dp用O(n^4)递推

code

——来自于已经毕业的一位何神的code
ORZ ORZ ORZ

#define PROC "table"#include <cstdio>#include <memory.h>#include <algorithm>using namespace std;typedef long long qw;#ifdef WIN32#define lld "%I64d"#else#define lld "%lld"#endif#define _l (qw)#define incm(a,b) (a=(_l (a) + (b))%mod)const int maxn = 109;const int mod = 1e9 + 7;int t[2][maxn * maxn], f[maxn * maxn], c[maxn][maxn], n, k;qw m;int modPow(int a, qw x) {    int s = 1;    for (; x; x >>= 1, a = _l a * a % mod)        if (x & 1)            s = _l s * a % mod;    return s;}void pre() {    memset(c, 0, sizeof(c));    for (int i = 0; i < maxn; ++ i)        c[i][0] = 1;    for (int i = 1; i < maxn; ++ i)        for (int j = 1; j <= i; ++ j)            c[i][j] = (_l c[i - 1][j] + c[i - 1][j - 1]) % mod;}int main() {    freopen(PROC ".in", "r", stdin);    freopen(PROC ".out", "w", stdout);    pre();    memset(t, 0, sizeof(t));    memset(f, 0, sizeof(f));    scanf("%d" lld "%d", &n, &m, &k);    for (int i = 0; i <= n && i <= k; ++ i) {        t[0][i] = modPow(c[n][i], m / n + 1);        t[1][i] = modPow(c[n][i], m / n);    }    f[0] = 1;    int c0 = m % n, c1 = n - c0;    for (int i = 0; i < c0; ++ i)        for (int j = k; j >= 0; -- j) {            int s = 0;            for (int l = 0; j - l >= 0 && l <= n; ++ l)                if (f[j - l])                    incm(s, _l f[j - l] * t[0][l]);            f[j] = s;        }    for (int i = 0; i < c1; ++ i)        for (int j = k; j >= 0; -- j) {            int s = 0;            for (int l = 0; j - l >= 0 && l <= n; ++ l)                if (f[j - l])                    incm(s, _l f[j - l] * t[1][l]);            f[j] = s;        }    printf("%d\n", f[k]);}

LGTB 与正方形

LGTB 最近迷上了正方形,现在他有n 个在二维平面上的点,请你告诉他在这些点中选4 个点能组成四条边
都平行于坐标轴的正方形的方案数有多少
输入
输入第一行包含一个整数n,代表点的数量
接下来n 行每行包含两个整数xi, yi,代表点的坐标
对于10% 的数据,1 <= n <= 50
对于30% 的数据,1 <= n <= 1000
对于100% 的数据,1 <= n <= 10^5,0 <= xi, yi <= 10^5
数据保证没有两点在同一位置
输出
输出包含一个整数代表方案数

样例
样例输入
5
0 0
0 2
2 0
2 2
1 1
样例输出
1
样例输入
9
0 0
1 1
2 2
0 1
1 0
0 2
2 0
1 2
2 1
样例输出
5

思路

多方向暴力,例横、纵、斜三种方式遍历,找最优方式n^2,可以过,注意打哈希,set要超时,STL较慢。

题解

标答

——就是上诉方式,横向与纵向搜索

#include <set>#include <cmath>#include <stack>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <cstdlib>#include <numeric>#include <vector>#include <ctime>#include <queue>#include <list>#include <map>#define pi acos(-1.0)#define INF 0x3f3f3f3f#define clr(x)  memset(x,0,sizeof(x));#define clrto(x,siz,y)  for(int xx=0;xx<=siz;xx++)  x[xx]=y;#define clrset(x,siz)  for(int xx=0;xx<=siz;xx++)  x[xx]=xx;#define clr_1(x) memset(x,-1,sizeof(x));#define clrmax(x) memset(x,0x3f,sizeof(x));#define clrvec(x,siz) for(int xx=0;xx<=siz;xx++)  x[xx].clear();#define fop2   freopen(".in","r",stdin); //freopen(".out","w",stdout);#define fop   freopen("in.txt","r",stdin);//freopen("out.txt","w",stdout);#define myprogram By_135678942570#define clrcpy(x,siz,y)  for(int xx=0;xx<siz;xx++)  x[xx]=y[xx];#define pb push_backusing namespace std;struct point{    int x,y;}P[100011];int SIZ=400;struct hash_map{    const static int mod=100007;    int head[mod];    struct hash_tables    {        long long key;        int val;        int next;    }ele[100007];    int N;    int getHash(long long x)    {        return x%mod;    }    void init()    {        memset(head,255,sizeof(head));        N=0;    }    int fint(long long x)    {        for(int i=head[getHash(x)];i!=-1;i=ele[i].next)            if(ele[i].key==x)                return i;        return -1;    }    void insert(long long x)    {        int tmp=getHash(x);        ele[N].key=x;        ele[N].val=0;        ele[N].next=head[tmp];        head[tmp]=N++;    }    int& operator [](long long x)    {        int tmp=fint(x);        if(tmp==-1)        {            insert(x);            return ele[N-1].val;        }        else return ele[tmp].val;    }}HT;vector<int>row[100111];vector<int>GREAT;vector<int>LESS;int main(){    // fop;    freopen("square.in", "r", stdin);    freopen("square.out", "w", stdout);    HT.init();    int n;    scanf("%d",&n);    for(int i=0;i<n;i++)    {        scanf("%d%d",&P[i].x,&P[i].y);        row[P[i].x].pb(P[i].y);        HT.insert(P[i].x*1000003ll+P[i].y);    }    for(int i=0;i<=100000;i++)        if(row[i].size()>=SIZ)            GREAT.pb(i);        else if(row[i].size()>0)            LESS.pb(i);    int res=0;    for(int i=0;i<LESS.size();i++)    {        int rowid=LESS[i];        for(int j=0;j<row[rowid].size();j++)            for(int k=j+1;k<row[rowid].size();k++)            {                int x1=rowid;                int y1=row[rowid][j],y2=row[rowid][k];                int x2=x1+abs(y1-y2);                int x22=x1-abs(y1-y2);                int f1=HT.fint(x2*1000003ll+y1);                int f2=HT.fint(x2*1000003ll+y2);                if(f1!=-1&&f2!=-1)                {                    res++;                }                if(x22>=0&&row[x22].size()>=SIZ)                {                    f1=HT.fint(x22*1000003ll+y1);                    f2=HT.fint(x22*1000003ll+y2);                    if(f1!=-1&&f2!=-1)                        res++;                }            }    }    for(int i=0;i<GREAT.size();i++)        sort(row[GREAT[i]].begin(),row[GREAT[i]].end());    for(int i=0;i<GREAT.size();i++)        for(int j=i+1;j<GREAT.size();j++)        {            int x1=GREAT[i];            int x2=GREAT[j];            int len=abs(x1-x2);            int ii=0,jj=0;            while(ii<row[x1].size()&&jj<row[x2].size())            {                if(row[x1][ii]==row[x2][jj])                {                    int f1=HT.fint(x1*1000003ll+row[x1][ii]+len);                    int f2=HT.fint(x2*1000003ll+row[x2][jj]+len);                    if(f1!=-1&&f2!=-1)                        res++;                    ii++,jj++;                }                else if(row[x1][ii]>row[x2][jj])                    jj++;                else ii++;            }        }    printf("%d\n",res);}

利用set的做法

*注:只有70%
——此程序为邓**所创,(我帮他调试的……)

#include<set>#include<queue>#include<cstdio>#include<vector>#include<cstring>#include<iostream>#include<algorithm>using namespace std;struct node{    int x,y;    bool operator<(const node&a)const    {        if(a.x!=x)return a.x>x;        else return a.y>y;    }}gg[100005];int small[100005],big[100005],low;int high,bb[100005],vis[100005];set<node>judge;vector<int>ma[100005];inline int read(){    int x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;}int main(){    freopen("square.in","r",stdin);    freopen("square.out","w",stdout);    int n=read(),maxn=0;    for(int i=1;i<=n;i++)    {        gg[i].x=read();gg[i].y=read();        ma[gg[i].x].push_back(gg[i].y);        judge.insert(gg[i]);        maxn=max(maxn,gg[i].x);        vis[gg[i].x]=1;    }    for(int i=0;i<=maxn;i++)        if(vis[i])        {            int num=ma[i].size();            if(num<400)                small[++low]=i;            else            {                big[++high]=i;                bb[i]=1;            }            sort(ma[i].begin(),ma[i].end());        }    int ans=0;    for(int i=1;i<=low;i++)        for(int j=0;j<ma[small[i]].size();j++)            for(int k=j+1;k<ma[small[i]].size();k++)            {                int tmp=small[i]-(ma[small[i]][k]-ma[small[i]][j]);                if(tmp)                    if(judge.count((node){tmp,ma[small[i]][j]}))                        if(judge.count((node){tmp,ma[small[i]][k]}))                            if(bb[tmp]==1)                                ans++;                tmp=small[i]+(ma[small[i]][k]-ma[small[i]][j]);                if(tmp<=maxn)                    if(judge.count((node){tmp,ma[small[i]][j]}))                        if(judge.count((node){tmp,ma[small[i]][k]}))                            ans++;            }    for(int i=1;i<=high;i++)        for(int j=i+1;j<=high;j++)        {            int op1=0,op2=0;            while(op1<ma[big[i]].size()&&op2<ma[big[j]].size())            {                if(ma[big[i]][op1]>ma[big[j]][op2])                    op2++;                else if(ma[big[i]][op1]<ma[big[j]][op2])                    op1++;                else                {                    int tmp=big[j]-big[i];                    if(judge.count((node){big[i],ma[big[i]][op1]+tmp}))                        if(judge.count((node){big[j],ma[big[j]][op2]+tmp}))                            ans++;                    op1++;op2++;                }            }        }    printf("%d",ans);    return 0;}

何jiaao的SBT

ORZ ORZ ORZ ORZ ORZ ORZ ORZ ORZ ORZ ORZ ORZ ORZ ORZ ORZ ORZ ORZ ORZ ORZ ORZ ORZ ORZ ORZ ORZ ORZ

——除了谢mj大神外,他是我见到的又一个手写平衡二叉树的人

#define PROC "square"#include <cstdio>#include <memory.h>#include <algorithm>using namespace std;struct point {    int x, y;};inline bool cmpPoint(const point& a, const point& b) {    return a. x < b. x || (a. x == b. x && a. y < b. y);}typedef long long qw;#ifdef WIN32#define lld "%I64d"#else#define lld "%lld"#endifconst int maxn = 100009;const int inf = 0x3f3f3f3f;namespace sbt {     //namespace你怕不怕!!!sbt你怕不怕!!!    const int maxnd = maxn * 3;    int ls[maxnd], rs[maxnd], sz[maxnd], vl[maxnd], tn;    void init() {        tn = 0;        sz[0] = 0;    }    inline void lRot(int& p) {        int q = rs[p];        rs[p] = ls[q];        ls[q] = p;        sz[p] = sz[ls[p]] + sz[rs[p]] + 1;        sz[q] = sz[ls[q]] + sz[rs[q]] + 1;        p = q;    }    inline void rRot(int& p) {        int q = ls[p];        ls[p] = rs[q];        rs[q] = p;        sz[p] = sz[ls[p]] + sz[rs[p]] + 1;        sz[q] = sz[ls[q]] + sz[rs[q]] + 1;        p = q;    }    inline void maintain(int& p, bool d) {        if (d) {            if (sz[ls[p]] + 1 > sz[rs[p]])                rRot(p);        }        else            if (sz[ls[p]] < sz[rs[p]] + 1)                lRot(p);    }    void ins(int& p, int v) {        if (!p) {            p = ++ tn;            ls[p] = 0;            rs[p] = 0;            sz[p] = 1;            vl[p] = v;        }        else {            if (v < vl[p])                ins(ls[p], v);            else                ins(rs[p], v);            ++ sz[p];            maintain(p, v < vl[p]);        }    }    int prv(int p, int v) {        if (!p)            return -inf;        else if (v > vl[p])            return max(vl[p], prv(rs[p], v));        else            return prv(ls[p], v);    }    int lower(int p, int v) {        if (!p)            return -inf;        else if (v == vl[p])            return v;        else if (v > vl[p])            return max(vl[p], lower(rs[p], v));        else            return lower(ls[p], v);    }};int n;qw ans;point a[maxn];int rx[maxn], ry[maxn], rk[maxn * 2];void addNode(int* rt, int p, int v) {    sbt :: ins(rt[p], v);}qw countSqu(int x, int y) {    int i = sbt :: prv(rx[x], y);    int j = sbt :: prv(ry[y], x);    int k = sbt :: prv(rk[y - x + maxn], x);    qw s = 0;    while (i > -inf && j > -inf && k > -inf)        if (y - i == x - j && j == k) {            //printf("(%d, %d), (%d, %d)\n", j, i, x, y);            ++ s;            i = sbt :: prv(rx[x], i);            j = sbt :: prv(ry[y], j);            k = sbt :: prv(rk[y - x + maxn], k);        }        else {            int vm = max(max(y - i, x - j), x - k);            if (y - i < vm)                i = sbt :: lower(rx[x], y - vm);            if (x - j < vm)                j = sbt :: lower(ry[y], x - vm);            if (x - k < vm)                k = sbt :: lower(rk[y - x + maxn], x - vm);        }    return s;}int main() {    freopen(PROC ".in", "r", stdin);    freopen(PROC ".out", "w", stdout);    memset(rx, 0, sizeof(rx));    memset(ry, 0, sizeof(ry));    memset(rk, 0, sizeof(rk));    sbt :: init();    scanf("%d", &n);    for (int i = 0; i < n; ++ i)        scanf("%d%d", &a[i]. x, &a[i]. y);    sort(a, a + n, cmpPoint);    for (int i = 0; i < n; ++ i) {        ans += countSqu(a[i]. x, a[i]. y);        addNode(rx, a[i]. x, a[i]. y);        addNode(ry, a[i]. y, a[i]. x);        addNode(rk, a[i]. y - a[i]. x + maxn, a[i]. x);    }    printf(lld "\n", ans);}

总结

今天就GG了
然后对于数论的知识我认为应该进一步在代码实现上加强。
另外,dp的灵活运用上仍有不足,搜索的方法上还可以有进一步突破。

1 0
原创粉丝点击