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; }