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;
}
京公网安备 11010502036488号