题解
今天是信心赛吗?
第一题——方程式(equation)
【题目描述】
- 给出n次方程的系数,求出所有根(重根也要输出)。
- n≤7 n ≤ 7 ,根的大小 1≤x≤20 1 ≤ x ≤ 20 且为整数
- 求根其实很简单,数据这么小,暴力就好了。主要问题是重根
- 手打模拟大除法的系数。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define LL long long
using namespace std;
void fff(){
freopen("equation.in","r",stdin);
freopen("equation.out","w",stdout);
}
int n,cnt;
LL a[10],t[10];
bool check(LL x){
if(cnt==0&&a[0]==0) return false;
LL sum=1;
for(int i=cnt-1;i>=0;i--){
sum=sum*x+1ll*a[i];
}
if(sum==0) return true;
return false;
}
void modify(LL x){
memcpy(t,a,sizeof(LL)*sizeof(t));
for(int i=cnt;i>=0;i--){
t[i]=a[i+1];
a[i]-=t[i]*(-x);
}
t[cnt]=0;
while(t[cnt]==0) cnt--;
memcpy(a,t,sizeof(LL)*sizeof(t));
}
int main(){
fff();
scanf("%d",&n);cnt=n;
for (int i=0;i<=n;i++) scanf("%lld",&a[i]);
for(LL i=1;i<=20;i++){
while(check(i)){
printf("%lld ",i);
modify(i);
}
}
}
第二题——高维宇宙(prime)
【题目描述】
- 给出n个整数,求有多少对数的和是质数。
- 范围 n≤40,2≤ai≤1000 n ≤ 40 , 2 ≤ a i ≤ 1000
- 数据这么小,一看就是二分图匹配。
- 先筛出质数,然后 n2 n 2 处理出能够相连的边。
- 然后求最大图匹配。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
void fff(){
freopen("prime.in","r",stdin);
freopen("prime.out","w",stdout);
}
const int MAXA=10000;
vector <int> prime;
bool visited[MAXA];
void oula(){
prime.clear();
for (int i=2;i<MAXA;i++){
if(!visited[i]) prime.push_back(i);
for(int j=0;j<(int)prime.size()&&prime[j]*i<MAXA;j++){
visited[prime[j]*i]=true;
if(i%prime[j]==0) break;
}
}
}
int n;
int a[44];
struct Edge{
int nxt,to;
}e[555];
int head[88],tot=0;
void add(int u,int v){
e[++tot].nxt=head[u];
e[tot].to=v;
head[u]=tot;
}
int toy[100],tox[100];
bool dfs(int u){
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(!visited[v]){
visited[v]=true;
if(!toy[v]||dfs(toy[v])){
tox[u]=v;
toy[v]=u;
return true;
}
}
}
return false;
}
int max_connect(){
int k=0;
for(int i=1;i<=n;i++){
memset(visited,false,sizeof(visited));
k+=dfs(i);
}
return k;
}
int main(){
fff();
oula();
scanf("%d",&n);
for (int i=1;i<=n;i++){
scanf("%d",&a[i]);
for(int j=1;j<i;j++){
int t=a[i]+a[j];
int pos=lower_bound(prime.begin(),prime.end(),t)-prime.begin();
if(prime[pos]==t){
add(i,j);
add(j,i);
}
}
}
printf("%d",max_connect()/2);
}
第三题——mahjong(mahjong)
【题目描述】
- 给出14张麻将牌,要求打出某一张牌之后听牌的张数最多
- 牌分为3种,条、桶、万,数量分别从1-9,每张最多4张。
- 听牌是指再拿一张就能够胡牌,如果一种牌有多张,那就算多种情况
- 胡牌需要有1组将牌和4组句子
- 将牌是指两张相同的牌
- 句子是指三张连续数量的牌(种类相同),或者三张相同的牌
- 暴力题,枚举打出每一张牌之后拿进每张牌之后最多的数量。
- 很明显,必须也只能有一组将牌。
- 出现相同的牌记得过滤。
- 记录当前的牌的张数。进行dfs。
- 真的没什么好讲的…直接看代码吧…
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
void fff(){
freopen("mahjong.in","r",stdin);
freopen("mahjong.out","w",stdout);
}
char ch[2];
int a[15];
int cnt[30];
bool visited[30],flag;
int Hash(){
int x=0;
swap(ch[0],ch[1]);
if(ch[0]=='s') x=10*0;
else if(ch[0]=='w') x=10;
else x=10*2;
x+=ch[1]-'0';
return x;
}
bool dfs(int i,int num,int rest){
if(flag) return true;
if(rest<0) return false;
if(i==30&&rest==0){
flag=true;
return flag;
}
if(i==30&&rest>0) return false;
if(cnt[i]==0) return dfs(i+1,num,rest);
bool ans=false;
if(cnt[i]>=1&&cnt[i+1]>=1&&cnt[i+2]>=1){
cnt[i]--;cnt[i+1]--;cnt[i+2]--;
ans=dfs(i,num,rest-3);
cnt[i]++;cnt[i+1]++;cnt[i+2]++;
}
if(ans){flag=true;return flag;}
if(cnt[i]>=2&&num==0){
cnt[i]-=2;
ans=dfs(i,num+1,rest-2);
cnt[i]+=2;
}
if(ans){flag=true;return flag;}
if(cnt[i]>=3){
cnt[i]-=3;
ans=dfs(i,num,rest-3);
cnt[i]+=3;
}
if(ans){flag=true;return flag;}
return false;
}
int main(){
fff();
for(int i=1;i<=14;i++){
scanf("%s",ch);
a[i]=Hash();
cnt[a[i]]++;
}
int ans_pos,ans_num=0;
for(int i=1;i<=14;i++){
if(visited[a[i]]) continue;
visited[a[i]]=true;
cnt[a[i]]--;
int count=0;
for(int j=1;j<=30;j++){
if(j%10==0) continue;
cnt[j]++;
flag=false;
count+=dfs(1,0,14)*(4-cnt[j]+1);
cnt[j]--;
}
cnt[a[i]]++;
if(count>ans_num){
ans_num=count;
ans_pos=i;
}
}
cout<<ans_pos<<' '<<ans_num;
}