【A】All X

【题目链接】点击打开链接

【解题思路】懂了(a/b)%mod = (a)%(b*mod)/b%mod,这个之后,这题完全就是水题。。。

【AC代码】

#include <queue>
#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;
#define ll long long
ll pow(ll a,ll n,ll mod){
    ll res=1;
    ll temp=a;
    while(n){
        if(n&1) res=res*temp%mod;
        temp=((temp%mod)*(temp%mod))%mod;
        n>>=1;
    }
    return res;
}

int main(){
    int T;
    ll x,m,k,c;
    scanf("%d",&T);
    for(int i=1; i<=T; i++){
        scanf("%I64d%I64d%I64d%I64d",&x,&m,&k,&c);
        ll ans=(pow(10,m,9*k)*x)%(9*k)-x;
        printf("Case #%d:\n",i);
        if(ans==9*c) puts("Yes");
        else         puts("No");
    }
    return 0;
}

【B】Sitting in Line

【题目链接】点击打开链接

【解题思路】简单状压dp,dp【i】【j】代表当前状态为i的时候,以a[j]结尾的a1*a2+a2*a3+a3*a4+...an-1*an的最大值。

【状态转移】dp[i|(1<<k)][k]=min(dp[i|(1<<k)][k],dp[i][j]+a[j]*a[k])

【AC代码】

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int N=16;
const int INF=0x3f3f3f3f;
int a[N],p[N],dp[1<<N][N];//状态为i,以a[j]结尾的最大的积
int n;
int main(){
    int T,cas;
    scanf("%d",&T);
    for(cas=1; cas<=T; cas++){
        scanf("%d",&n);
        for(int i=0; i<n; i++){
            scanf("%d%d",&a[i],&p[i]);
        }
        //INIT 1.
        for(int i=0; i<(1<<n); i++)
            for(int j=0; j<n; j++)
                dp[i][j]=-INF;
        //INIT 2.
        for(int i=0; i<n; i++)
            if(p[i]==0||p[i]==-1) //当p[i]==0或者p[i]==-1才可以初始化
                dp[1<<i][i]=0;
        //DP
        for(int s=0; s<(1<<n); s++){
            for(int i=0; i<n; i++){
                if(dp[s][i]!=-INF){
                    for(int k=0; k<n; k++){//当是第p[k]个或者p[k]==-1的时候可以往里面放
                        if(((s&(1<<k))==0&&(p[k]==__builtin_popcount(s)||p[k]==-1)))
                            dp[s|(1<<k)][k]=max(dp[s|(1<<k)][k],dp[s][i]+a[i]*a[k]);
                    }
                }
            }
        }
        //get ans.
        int ans=-INF;
        for(int i=0; i<n; i++){
            ans=max(ans,dp[(1<<n)-1][i]);
        }
        printf("Case #%d:\n",cas);
        printf("%d\n",ans);
    }
    return 0;
}

【F】BD String.

【题目链接】点击打开链接

【解题思路】规律和递归!

从字符串规则可以看出以下几点

①S(n)的串长度为;

②S(n)中B的个数为个(以正中间的B为中心,假设左边有x个B,那么右边有个,即左边B的个数+右边B的个数=S(n-1)的串长度)

远大于,故只是吓唬我们的

由上述几点可知,此题并没有表面上那么吓人

要求区间[l,r]内B的个数,我们可以转化为求[1,r]-[1,l-1]

而求区间[1,x]内B的个数,又可以如上述第②条所说,拆成3段,递归求解

比如x=12时,S=BBDBBDDBBBDD……

拆成3段如下:

右边4个是多余的,但是因为右边是由reverse+flip得到的,求右边4个中B的个数可以转化成求4-([1,7]中B的个数-[1,3]中B的个数)

而[1,3]中的个数又是得递归求解的

【AC代码】

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long
ll l,r;
//2^n==x.
ll solve(ll x){
    if(x==0) return 0;
    ll m=0;
    ll ans;
    while(m<x) m=m*2+1;
    m=(m-1)/2;
    ans=(m+1)/2;
    ll curlen=x-m-1;
    return ans+1+curlen-(ans-solve(m-curlen));
}

int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%I64d%I64d",&l,&r);
        ll ans=solve(r)-solve(l-1);
        printf("%I64d\n",ans);
    }
    return 0;
}

【G】 Gym Class
【题目链接】 点击打开链接

【解题思路】拓扑排序+贪心

众所周知,为了使每个人给的评分尽可能高,在没有条件的情况下,必定是ID高的排前面来得最优

但是度度熊没有那么善良

ID为B的同学不能排在A前面,好吧,怎么做呢?

对于这种调度问题,我们不妨用拓扑排序来求解

假设B不能排在A前面,那么我就在AB之间画一条从A指向B的边,那么我们可以得到一幅有向图

我们要按ID从大往小排,同时要考虑当前这位同学是否有特殊要求

上面有向图中,凡入度为0的结点,表示没有同学不希望该同学排在它的前面,故该同学可以按照ID从大往小排

所以此题的做法是,每次将入度为0的结点放入优先队列中,选取ID最大的结点先排,然后将该ID的同学讨厌的所有同学入度-1,若入度变为0同样要放入优先队列判断ID先后,这里建图可以邻接表实现,也可以利用一些vector


【AC代码】
#include <queue>
#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;
#define ll long long
const int inf=0x3f3f3f3f;
struct cmp{
   bool operator()(int &a,int &b){
       return a<b;
   }
};
int n,m;
int in[100005];//记录入度
priority_queue<int,vector<int>,cmp>pq;//最大值优先
vector<int>v[100005];//存图

int main(){
    int T;
    int x,y;
    scanf("%d",&T);
    while(T--){
        ll ans=0;
        int minid=inf;
        scanf("%d%d",&n,&m);
        memset(in,0,sizeof(in));
        for(int i=1; i<=n; i++) v[i].clear();
        while(!pq.empty())      pq.pop();
        for(int i=0; i<m; i++){
            scanf("%d%d",&x,&y);
            in[y]++;
            v[x].push_back(y);
        }
        for(int i=1; i<=n; i++){
            if(!in[i]) pq.push(i);
        }
        while(!pq.empty()){
            int temp=pq.top();
            pq.pop();
            minid=min(minid,temp);
            ans+=minid;
            for(int i=0; i<v[temp].size(); i++){
                in[v[temp][i]]--;
                if(in[v[temp][i]]==0) pq.push(v[temp][i]);
            }
        }
        printf("%lld\n",ans);
    }
    return 0;
}