Divisibility

思路:这个题目有点绕,也就是要我们证明输入是否满足这个命题,也就是要我们去验证这个命题是否成立,我是通过模拟来发现的规律,也就是b--是否可以整除x,如果可以就满足。至于具体的解释看官方题解即可。
图片说明
代码:

#include<iostream> 
using namespace std;
typedef long long ll;
int main(){
    int t;
    cin>>t;
    while(t--){
        ll b,x;
        cin>>b>>x;
        b--;
        if(b%x==0)  cout<<"T"<<endl;
        else  cout<<"F"<<endl;
    }
    return 0;
}

Little rabbit's equation

题意:给出一个表达式,判断满足该表达式下的最小进制数并且输出。
思路:注意以下几点即可。
1、我们会发现题目限制了进制数只能在2-16,那么我们可以对每次输入直接进行枚举。
2、我们还会发现,我们的枚举的进制至少要大于输入中出现的最大的那个数位。
3、对于除法,还有一个要注意的事项是如果不能整除的话,那么一定是输出-1的。
4、注意可能爆int。
然后,我们要从一个字符串里面提取出3个表达式来,进行验证即可。

#include<bits/stdc++.h>
using namespace std;
string a,b,ans;
string s;
char op;
bool key;
typedef long long ll;
bool judge(int r){
    ll x=0,y=0;
    int len1=a.size();
    for(int i=0;i<len1;i++){
        int tmp;
        if(a[i]<='9'&&a[i]>='0')  tmp=a[i]-'0';
        else  tmp=a[i]-'A'+10;
        x=x*r+tmp;
    }
    int len2=b.size();
    for(int i=0;i<len2;i++){
        int tmp;
        if(b[i]<='9'&&b[i]>='0')  tmp=b[i]-'0';
        else  tmp=b[i]-'A'+10;
        y=y*r+tmp;
    }
    int len3=ans.size();
    ll z=0;
    for(int i=0;i<len3;i++) {
        int tmp;
        if(ans[i]<='9'&&ans[i]>='0')  tmp=ans[i]-'0';
        else  tmp=ans[i]-'A'+10;
        z=z*r+tmp;
    }
    if(op=='+'&&x+y==z){
        return true;
    }
    else if(op=='-'&&x-y==z){
        return true;
    }
    else if(op=='*'&&x*y==z){
        return true;
    }
    else if(op=='/'&&x/y==z){
        if(x%y==0)  return true;
        else{
            key=true;
            return false;
        }
    }
    return false;
}
int main(){
    while(cin>>s){
        getchar();
        key=false;
        a.clear(),b.clear(),ans.clear();
        int len=s.size();
        int i;
        for(i=0;i<len;i++){
            if(s[i]=='+'||s[i]=='-'||s[i]=='*'||s[i]=='/'){
                op=s[i];
                break;
            }
            else   a+=s[i];
        }
        for(i++;i<len;i++){
            if(s[i]=='=')  break;
            else  b+=s[i];
        }
        for(i++;i<len;i++)  ans+=s[i];
        int mx=-1;
        for(i=0;i<len;i++){
            if(s[i]<='9'&&s[i]>='0')  mx=max(mx,s[i]-'0');
            else if(s[i]<='F'&&s[i]>='A')  mx=max(mx,s[i]-'A'+10);
        }
        bool flag=true;
        mx=max(1,mx);
        for(i=mx+1;i<=16;i++){
            if(judge(i)){
                flag=false;
                printf("%d\n",i);
                break;
            }
            if(key)  break;
        }
        if(flag)  printf("-1\n");
    }
    return 0;
}

Road To The 3rd Building

题意:就是有一个序列,每个点的权值为s[i],序列中i到j的(i<j)这一段的期望,最后求出所有的期望总和并且输出。
思路:预处理+逆元。首先,通过从小范围的模拟中我们可以发现,我们找对于长度为j的序列,我们寻找到下标为i的那个元素出现的次数,得出现的次数为min{i,j,n+1-i,n+1-j}。那么,总的贡献和就是

​首先,我们先求出1-200010对应的逆元存入inv数组里面,然后根据输入进行线性求逆元。同时,我们知道左右出现的次数具有对称性,即我们只考虑(n-1)/2的情况,因为下标为0和下标为n-1的两个数出了权值不同,其他都是等价的。过程中注意处理mod的情况。
代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
ll a[200010],sum[200010];
ll s[200010];
ll inv[200010];

ll binarypow(ll a,ll b){
    if(b==0)  return 1;
    if(b&1)  return a*binarypow(a,b-1)%mod;
    else{
        ll mul=binarypow(a,b/2);
        return mul*mul%mod;
    }
}

int main(){
    for(ll i=1;i<=200010;i++){
        inv[i]=binarypow(i,mod-2)%mod;
    }
    int T;
    scanf("%d",&T);
    while(T--){
        ll n;
        scanf("%lld",&n);
        memset(sum,0,sizeof(sum));
        memset(s,0,sizeof(s));
        for(int i=1;i<=n;i++){
            scanf("%lld",&a[i]);
            sum[i]=(sum[i-1]+a[i]%mod)%mod;
        }
        ll ans=0;
        for(int i=0;i<(n+1)/2;i++){
            s[i+1]=(s[i]+sum[n-i]-sum[i]+mod)%mod;
            if((i+1)!=n-i) ans=(ans+s[i+1]*((inv[i+1]+inv[n-i])%mod)%mod)%mod;
            else  ans=(ans+s[i+1]*inv[i+1]%mod)%mod;
        }
        printf("%lld\n",ans*binarypow(n*(n+1)/2%mod,mod-2)%mod);
    }
    return 0;
}