1002 Little Rabbit’s Equation
题目链接:杭电第六场1002
题目理解:输入一个等式,判断在(2~16)进制之内是否成立,成立则输出对应进制(多个满足输出最小),不成立输出-1。
参考队内的AC代码,在自己的理解下稍微改动,整体思路是参考的。
具体解释见代码
#include<stdio.h>
#include<iostream>
#include<math.h>
#include<string.h>
#include <algorithm>
#include <numeric>
#include <vector>
#include <functional>
#include <list>
#include <ctype.h>
#include<map>
#include <set>
#define N 6000005
#define M 100
#define ll long long
#define mod 998244353
using namespace std;
string num1,num2,num3;
string num[3];
bool flag;
int trans(string a,int n){ //将n进制数转换为10进制方便计算
int k=0,len=a.length()-1,m=0;
while(a[k]=='0') k++;//消除前缀零
int sum=0;
for(int i=len;i>=k;i--){
int x;
char b=toupper(a[i]);
if (b >= 'A' && a[i] <= 'Z') x = b - 'A' + 10;
if (b >= '0' && a[i] <= '9') x = b - '0';
sum+=pow(n,m++)*x;
}
return sum;
}
void solve(char op){
int st=2,end=16;
string temp=num[0]+num[1]+num[2];
int max_num=0;
for(int i=0;i<temp.length();i++){
int x;
if (temp[i] >= 'A' && temp[i] <= 'Z') x = temp[i] - 'A' + 10;
if (temp[i] >= '0' && temp[i] <= '9') x = temp[i] - '0';
max_num = max(max_num, x);
}
st=max(st,max_num+1);//通过上述操作可以使st从最大可能的进制开始,而不是从2开始,这样可以使时间复杂度减少
for (int i = st; i <= end; i++) {
double number1 = trans(num[0],i);
double number2 = trans(num[1],i);
double number3 = trans(num[2],i);
switch(op) {
case '+': {
if (number1 + number2 == number3) {
printf ("%d", i);
return;
}
break;
}
case '-': {
if (number1 - number2 == number3) {
printf ("%d", i);
return;
}
break;
}
case '*': {
if (number1 * number2 == number3) {
printf ("%d", i);
return;
}
break;
}
case '/': {
if (number1 * 1.0 / number2 == number3) {
printf ("%d", i);
return;
}
break;
}
}
}
printf ("-1");
return;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
string s;
while(cin>>s){
fill(num,num+3,"");//储存三个运算数
int k=0;
char op;
for(int i=0;i<s.length();i++){
if(s[i]>='0'&&s[i]<='9'||(s[i]>='A'&&s[i]<='F'))
num[k]+=s[i];
else {//当为运算符时用op记录运算符,并且使k++开始记录下一个运算数
if(s[i]!='=') op=s[i];
k++;
}
}
solve(op);puts("");
}
}
对于我来说,我认为最难想到的是
int max_num=0;
for(int i=0;i<temp.length();i++){
int x;
if (temp[i] >= 'A' && temp[i] <= 'Z') x = temp[i] - 'A' + 10;
if (temp[i] >= '0' && temp[i] <= '9') x = temp[i] - '0';
max_num = max(max_num, x);
}
st=max(st,max_num+1);//通过上述操作可以使st从最大可能的进制开始,而不是从2开始,这样可以使时间复杂度减少
如果是我可能直接从2开始查找。
1009
题目链接:杭电多校第六场1009
#include<iostream>
#include<math.h>
#include<string.h>
#include <algorithm>
#include <numeric>
#include <vector>
#include <functional>
#include <list>
#include <ctype.h>
#include<map>
#include <set>
#define M 100
#define ll long long
using namespace std;
int main() {
int t;
scanf("%d", &t);
while (t--) {
ll b, x;
scanf("%lld %lld", &b, &x);
if (b % x == 1)
printf("T\n");
else
printf("F\n");
}
return 0;
}
1001
题目链接:杭电多校第六场1001
#include<iostream>
#include<math.h>
#include<string.h>
#include <algorithm>
#include <numeric>
#include <vector>
#include <functional>
#include <list>
#include <ctype.h>
#include<map>
#include <set>
#define M 100
#define ll long long
using namespace std;
const int N=200005;
const int mod=1e9+7;
ll a[N],s[N];
ll quick(ll a, ll b)
{
ll ans = 1;
while(b)
{
if(b & 1) ans = ans * a % mod;
a = a * a % mod;
b >>= 1;
}
return ans % mod;
}
long long inv(long long a) {
return quick( a ,mod - 2);
}
int main(){
int t;
scanf("%d",&t);
while(t--){
memset(a,0,sizeof(a));
memset(s,0,sizeof(s));
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
s[i]=(s[i-1]+a[i]%mod)%mod;//前缀和
}
ll k=0,ans=0;
for(int i=1;i<=n/2;i++){
k=(k+s[n-i+1]-s[i-1]+mod)%mod;//s[n-i+1]-s[i-1] z这个试子即取(n-i+1)到(i-1) 的和 例i=1时取 1~n的和
ans=(ans+k*inv(i)%mod) %mod;
ans=(ans+k*inv(n-i+1)%mod)%mod;//i和n-i+1对应分子相同
}
if(n%2!=0) {//当n为奇数时,最中间的那个要特殊考虑
k+=a[n/2+1]%mod;
ans=(ans+k*inv(n/2+1)%mod)%mod;
}
ans=(ans*inv((ll)n*(n+1)/2%mod))%mod;//n*(n+1)/2是参与分子计算的总个数,注意前面要加(ll)(从队友那学来的,开始没加就wa了)
printf("%lld\n",ans);
}
}
1005
题目链接:杭电多校第六场1005
dp[i][j][val]:[i,j]区间内是否能计算出valval。
于是可得转移方程:
dp[i][j][v1+v2]=dp[i][mid][v1]+dp[mid+1][j][v2]
dp[i][j][v1∗v2]=dp[i][mid][v1]*dp[mid+1][j][v2]
上述转移方程参考博客:参考
#include<iostream>
#include<math.h>
#include<string.h>
#include <algorithm>
#include <numeric>
#include <vector>
#include <functional>
#include <list>
#include <ctype.h>
#include<map>
#include <set>
#define MAX 0x3f3f3f
#define ll long long
using namespace std;
const int N=5050;
int re[N];
string s=" 1145141919114514191911451419191145141919";
set<int> dp[20][20];
void dfs(int l,int r){
if((int)dp[l][r].size()!=0) return;
if(r-l+1<=4){//长度>4的话必大于5000+
int num=0;
for(int i=l;i<=r;i++){
num=num*10+(s[i]-'0');
}
if(num<=5000) dp[l][r].insert(num);
}
for(int i=l;i<r;i++){
dfs(l,i);
dfs(i+1,r);
set<int>::iterator a,b;
for(a=dp[l][i].begin();a!=dp[l][i].end();a++) {
for(b=dp[i+1][r].begin();b!=dp[i+1][r].end();b++){
if(*a+*b<=5000) dp[l][r].insert(*a+*b);
if(*a* *b<=5000) dp[l][r].insert(*a**b);
}
}
}
}
int main(){
dfs(1,13);
memset(re,0x3f,sizeof(re));
for(int i=1;i<=13;i++){
set<int>::iterator x;
for(x=dp[1][i].begin();x!=dp[1][i].end();x++){
re[*x]=min(re[*x],i);
}
}
re[3]=re[7]=-1;//根据题解只有当n=3和n=7时输出-1
int t;
scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
printf("%d\n",re[n]);
}
}