杭电第六场补题(待完善)

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值