A.小A买彩票

一开始想到排列组合,但是发现太菜不会写orz。看到数据范围小,想直接暴力,TLE,然后,联想到记忆化搜素减少搜索,所以应该是dp。但是菜鸡并不会设计状态(划掉),所以,只能写dfs+记忆化搜索。

#include <iostream>
#include <map>
#include <ctime>
#include <vector>
#include <climits>
#include <algorithm>
#include <random>
#include <cstring>
#include <cstdio>
#include <map>
#include <set>
#include <bitset> 
#include <queue>
#define inf 0x3f3f3f3f
#define IOS ios_base::sync_with_stdio(0); cin.tie(0);
#define rep(i, a, n) for(register int i = a; i <= n; ++ i)
#define per(i, a, n) for(register int i = n; i >= a; -- i)
#define ONLINE_JUDGE
using namespace std;
typedef long long ll;
const int mod=1e9+7;
template<typename T>void write(T x)
{
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    if(x>9)
    {
        write(x/10);
    }
    putchar(x%10+'0');
}

template<typename T> void read(T &x)
{
    x = 0;char ch = getchar();ll f = 1;
    while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}
    while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;};
ll ksm(ll a,ll n){//看是否要mod 
    ll ans=1;
    while(n){
        if(n&1) ans=(ans*a);
        a=a*a;
        n>>=1;
    }
    return ans;
}
//==============================================================
int n;
ll f[200][200];
ll dfs(ll k,ll pos){
    if(f[k][pos]!=-1) return f[k][pos];
    if(k>n){
        if(pos>=3*n) return 1;
        else return 0;
    }
    ll res=0;
    rep(i,1,4){
        res+=dfs(k+1,pos+i);
    }
    f[k][pos]=res;
    return res;
}


int main()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif
    clock_t c1 = clock();
    //===========================================================
    read(n);
    memset(f,-1,sizeof(f));
    ll ans=dfs(1,0);
    if(ans==0){
        puts("0/1");
        return 0;
    }
    ll fm=ksm(4,n);
    ll gg=gcd(fm,ans);
    printf("%lld/%lld\n",ans/gg,fm/gg);
    //===========================================================
    std::cerr << "Time:" << clock() - c1 << "ms" << std::endl;
    return 0;
}

B.「金」点石成金

以前写过,数据范围小,所以直接搜索就行了。

#include <iostream>
#include <map>
#include <ctime>
#include <vector>
#include <climits>
#include <algorithm>
#include <random>
#include <cstring>
#include <cstdio>
#include <map>
#include <set>
#include <bitset> 
#include <queue>
#define inf 0x3f3f3f3f
#define IOS ios_base::sync_with_stdio(0); cin.tie(0);
#define rep(i, a, n) for(register int i = a; i <= n; ++ i)
#define per(i, a, n) for(register int i = n; i >= a; -- i)
#define ONLINE_JUDGE
using namespace std;
typedef long long ll;
const int mod=1e9+7;
template<typename T>void write(T x)
{
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    if(x>9)
    {
        write(x/10);
    }
    putchar(x%10+'0');
}

template<typename T> void read(T &x)
{
    x = 0;char ch = getchar();ll f = 1;
    while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}
    while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;};
ll ksm(ll a,ll n){//看是否要mod 
    ll ans=1;
    while(n){
        if(n&1) ans=(ans*a)%mod;
        a=a*a%mod;
        n>>=1;
    }
    return ans%mod;
}
//==============================================================
const int maxn=20;
ll n,a[maxn],b[maxn],c[maxn],d[maxn];
ll ans=-inf;
void dfs(int idx,ll cai,ll mo){
    if(idx>n){
        ans=max(ans,cai*mo);
        return;
    }
    rep(i,1,2){
        if(i==1){
            dfs(idx+1,cai+a[idx],max(0ll,mo-b[idx]));
        }
        if(i==2){
            dfs(idx+1,max(cai-d[idx],0ll),mo+c[idx]);
        }
    }
}

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif
    clock_t c1 = clock();
    //===========================================================
    read(n);
    rep(i,1,n){
        read(a[i]),read(b[i]),read(c[i]),read(d[i]);
    }
    dfs(1,0,0);
    write(ans);
    //===========================================================
    std::cerr << "Time:" << clock() - c1 << "ms" << std::endl;
    return 0;
}

C.小阳的贝壳

感觉是这次最难的题目了。这道题询问有三种:给区间加,求区间差值最大,求区间gcd。如果只有前两个,还是比较好想到维护一个差分数组的。但是对于第三个,我们需要知道结论:


再衍生一下就是:
因此,我们只需要维护差分数组就行了。

#include <iostream>
#include <map>
#include <ctime>
#include <vector>
#include <climits>
#include <algorithm>
#include <random>
#include <cstring>
#include <cstdio>
#include <map>
#include <set>
#include <bitset> 
#include <queue>
#define int long long
#define inf 0x3f3f3f3f
#define IOS ios_base::sync_with_stdio(0); cin.tie(0);
#define rep(i, a, n) for(register int i = a; i <= n; ++ i)
#define per(i, a, n) for(register int i = n; i >= a; -- i)
//#define ONLINE_JUDGE
using namespace std;
typedef long long ll;
const int mod=1e9+7;
template<typename T>void write(T x)
{
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    if(x>9)
    {
        write(x/10);
    }
    putchar(x%10+'0');
}

template<typename T> void read(T &x)
{
    x = 0;char ch = getchar();ll f = 1;
    while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}
    while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;};
ll ksm(ll a,ll n){//¿´ÊÇ·ñÒªmod 
    ll ans=1;
    while(n){
        if(n&1) ans=(ans*a)%mod;
        a=a*a%mod;
        n>>=1;
    }
    return ans%mod;
}
//==============================================================
const int maxn=1e5+10;
#define lson (rt<<1)
#define rson (rt<<1|1)
struct node{
    int l,r,m,GCD;
    int sum;
}tree[maxn<<2];
int a[maxn];
int n,m;
void pushup(int rt){
    tree[rt].m=max(tree[lson].m,tree[rson].m);
    tree[rt].GCD=gcd(tree[lson].GCD,tree[rson].GCD);
    tree[rt].sum=tree[lson].sum+tree[rson].sum;
}
void build(int l,int r,int rt){
    tree[rt].l=l,tree[rt].r=r;
    if(l==r){
        tree[rt].m=tree[rt].GCD=abs(a[l]);
        tree[rt].sum=a[l];
        return;
    }
    int m=(l+r)>>1;
    build(l,m,rt<<1);
    build(m+1,r,rt<<1|1);
    pushup(rt);
}

void modify(int tar,int val,int rt){
    int l=tree[rt].l,r=tree[rt].r;
    if(l==r){
        a[l]+=val;
        tree[rt].m=tree[rt].GCD=abs(a[l]);
        tree[rt].sum=a[l];
        return ;
    }
    int m=(l+r)>>1;
    if(tar<=m) modify(tar,val,lson);
    else modify(tar,val,rson); 
    pushup(rt);
}

int qm(int ql,int qr,int rt){
    int l=tree[rt].l,r=tree[rt].r;
    if(ql<=l&&r<=qr){
        return tree[rt].m;
    }
    int m=(l+r)>>1;
    int res=0;
    if(ql<=m) res=max(res,qm(ql,qr,lson));
    if(qr>m) res=max(res,qm(ql,qr,rson));
    return res;
}
int qgcd(int ql,int qr,int rt){
    int l=tree[rt].l,r=tree[rt].r;
    if(ql<=l&&qr>=r){
        return tree[rt].GCD;
    }
    int res=0;
    int m=(l+r)>>1;
    if(ql<=m) res=gcd(res,qgcd(ql,qr,lson));
    if(m<qr) res=gcd(res,qgcd(ql,qr,rson));
    return res;
}
int qsum(int ql,int qr,int rt){
    int l=tree[rt].l,r=tree[rt].r;
    if(ql<=l&&r<=qr){
        return tree[rt].sum;
    }
    int m=(l+r)>>1;
    int res=0;
    if(ql<=m) res+=qsum(ql,qr,lson);
    if(qr>m) res+=qsum(ql,qr,rson);
    return res;
}

signed main()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif
    clock_t c1 = clock();
    //===========================================================
    read(n),read(m);
    rep(i,1,n) read(a[i]);
    per(i,1,n) a[i]-=a[i-1];
    build(1,n,1);
    while(m--){
        int opt;
        read(opt);
        if(opt==1){
            int l,r,x;
            read(l),read(r),read(x);
            modify(l,x,1);
            if(r<n) modify(r+1,-x,1);
        }
        else if(opt==2){
            int l,r;
            read(l),read(r);
            if(l==r){
                cout<<0<<endl;
                continue;
            }
            write(qm(l+1,r,1));
            putchar('\n');
        }
        else if(opt==3){
            int l,r;
            read(l),read(r);
            int t=qsum(1,l,1);
            if(l==r){
                write(t);
            }
            else{
                write(gcd(qgcd(l+1,r,1),t));
            }
            putchar('\n');
        }
    }
    //===========================================================
    std::cerr << "Time:" << clock() - c1 << "ms" << std::endl;
    return 0;
}

D.Forsaken喜欢字符串

纯暴力题,暴力统计每个字符串的每个子串的出现次数,后暴力求和就行了,具体看代码:

#include <iostream>
#include <map>
#include <ctime>
#include <vector>
#include <climits>
#include <algorithm>
#include <random>
#include <cstring>
#include <cstdio>
#include <map>
#include <set>
#include <bitset> 
#include <queue>
#define inf 0x3f3f3f3f
#define IOS ios_base::sync_with_stdio(0); cin.tie(0);
#define rep(i, a, n) for(register int i = a; i <= n; ++ i)
#define per(i, a, n) for(register int i = n; i >= a; -- i)
#define ONLINE_JUDGE
using namespace std;
typedef long long ll;
const int mod=1e9+7;
template<typename T>void write(T x)
{
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    if(x>9)
    {
        write(x/10);
    }
    putchar(x%10+'0');
}

template<typename T> void read(T &x)
{
    x = 0;char ch = getchar();ll f = 1;
    while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}
    while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;};
ll ksm(ll a,ll n){//¿´ÊÇ·ñÒªmod 
    ll ans=1;
    while(n){
        if(n&1) ans=(ans*a)%mod;
        a=a*a%mod;
        n>>=1;
    }
    return ans%mod;
}
//==============================================================
const int maxn=5e4+10;
int n,k,q;
string str[maxn];
map<string,int> ans;
void deal(){
    rep(i,1,n){
        rep(l,1,k){
            rep(j,0,k-l){
                ans[str[i].substr(j,l)]++;
            }
        }
    }
}
int solve(int x,int len){
    int res=0;
    rep(j,0,k-len){
        int cnt=0;
        string sub=str[x].substr(j,len);
        rep(i,0,k-len){
            if(str[x].substr(i,len)==sub){
                cnt++;
            }
        }
        res+=(ans[sub]-cnt)*sub.length();
    }
    return res;
}

int main()
{
    IOS;
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif
    clock_t c1 = clock();
    //===========================================================
    cin>>n>>k;
    rep(i,1,n){
        cin>>str[i];
    }
    cin>>q;
    deal();
    while(q--){
        int x,len;
        cin>>x>>len;
        cout<<solve(x,len)<<endl;
    }
    //===========================================================
    std::cerr << "Time:" << clock() - c1 << "ms" << std::endl;
    return 0;
}

E.Board

思维题。因为每一次加都是针对一整行或一整列的,所以,我们挑选形成对角线的一组(像二阶行列式求值的时候的,斜的那n个数),刚好都处于不同行,不同列,加起来就是修改过程中所有加数的和sum1了。
同理,-1所在的那条对角线也应该是这个和,这时候,我们就可以利用刚才求出的sum1,以及-1所在对角线的,其他数的和sum2,做个差值,求出来的,就是-1处缺少的这个数。

#include <iostream>
#include <map>
#include <ctime>
#include <vector>
#include <climits>
#include <algorithm>
#include <random>
#include <cstring>
#include <cstdio>
#include <map>
#include <set>
#include <bitset> 
#include <queue>
#define inf 0x3f3f3f3f
#define IOS ios_base::sync_with_stdio(0); cin.tie(0);
#define rep(i, a, n) for(register int i = a; i <= n; ++ i)
#define per(i, a, n) for(register int i = n; i >= a; -- i)
#define ONLINE_JUDGE
using namespace std;
typedef long long ll;
const int mod=1e9+7;
template<typename T>void write(T x)
{
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    if(x>9)
    {
        write(x/10);
    }
    putchar(x%10+'0');
}

template<typename T> void read(T &x)
{
    x = 0;char ch = getchar();ll f = 1;
    while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}
    while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;};
ll ksm(ll a,ll n){//看是否要mod 
    ll ans=1;
    while(n){
        if(n&1) ans=(ans*a)%mod;
        a=a*a%mod;
        n>>=1;
    }
    return ans%mod;
}
//==============================================================
const int maxn=1e3+10;
int a[maxn][maxn];
int hang[maxn],lie[maxn];
int n;


int main()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif
    clock_t c1 = clock();
    //===========================================================
    read(n);
    memset(hang,inf,sizeof(hang));
    memset(lie,inf,sizeof(lie));
    int h,l;
    rep(i,1,n){
        rep(j,1,n){
            read(a[i][j]);
            if(a[i][j]==-1){
                h=i,l=j;
            }
        }
    }
    int p1=h+1,p2=l;
    int cnt=0;
    int s=0;
    while(cnt<n){
        cnt++;
        s+=a[p1][p2];
        p1++,p2++;
        if(p1>n) p1%=n;
        if(p2>n) p2%=n;
    }
    int pp1=h,pp2=l;
    int cntt=0;
    int ss=0;
    while(cntt<n){
        cntt++;
        if(a[pp1][pp2]!=-1){
            ss+=a[pp1][pp2];
        }
        pp1++,pp2++;
        if(pp1>n) pp1%=n;
        if(pp2>n) pp2%=n;
    }
    write(s-ss);
    //===========================================================
    std::cerr << "Time:" << clock() - c1 << "ms" << std::endl;
    return 0;
}