ACM题集:https://blog.csdn.net/weixin_39778570/article/details/83187443
题目集合:http://acm.hdu.edu.cn/listproblem.php?vol=11
2061 Treasure the new start, freshmen!
#include<bits/stdc++.h>
#define fo(i,j,n) for(int i=j; i<=n; ++i)
int t,n;
double ans, crd, sco, c_sum, cs_sum;
char s[40];
int main(){
scanf("%d",&t);
while(t--){
scanf("%d", &n);
bool flat = 1;
c_sum=0, cs_sum=0;
fo(i, 1, n){
scanf("%s%lf%lf", s, &crd, &sco);
if(sco<60) flat = 0;
c_sum += crd;
cs_sum += crd*sco;
}
ans = cs_sum/c_sum;
if(t>=1 && !flat) printf("Sorry!\n\n");
else if(!flat) printf("Sorry!\n");
else if(t>=1) printf("%.2f\n\n", ans);
else printf("%.2f\n", ans);
}
return 0;
}
2062 Subset sequence
/* 找规律,找方程 */
{1}
{1,2}
{1,2,3}
{1,3}
{1,3,2}
{2}
{2,1}
{2,1,3}
{2,3}
{2,3,1}
{3}
{3,1}
{3,1,2}
{3,2}
{3,2,1}
这到题的集合排序是这样子的 字典排序 头大则大 头小则小 不优先考虑长度
f(n) 表示按字典排序的集合总数 g(n) 表示每个小组的集合数量
f(n) = (f(n-1)+1) * n
g(n) = f(n)/n
= f(n-1)+1
g(n-1) = f(n-1)/(n-1)
g(n) = g(n-1)*(n-1) + 1
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n, m, g[22], t, a[22];
void init(){
// 数量为n的分组长度表
g[1] = 1;
for(int i=2; i<=21; ++i){
g[i] = (g[i-1]) * (i-1) + 1;
}
}
int main(){
init();
while(scanf("%lld%lld", &n, &m)!=EOF){
for(int i=1; i<=20; i++) a[i] = i;
while(n){
t = (m-1) / g[n] + 1; // 在n个数的字典集合中,m在第t组
printf("%d", a[t]);
for(int i=t; i<=20; i++) a[i] = a[i+1]; // 比输出数字大的要左移一位, 比如,如果现在是第2组,那么下该组下的第2组就是3,第3组就是4
m -= (t-1) * g[n] + 1; // 需要减去前面的组数量以及头部空集,得到在新的组里是第几个数
if(m<=0) { printf("\n");break; }
else printf(" ");
--n; // 集合规模减1,问题规模缩小
}
}
return 0;
}
2063 过山车
二分图 最大匹配问题
#include<bits/stdc++.h>
#define fo(i,j,n) for(int i=j; i<=n; ++i)
#define ll long long
using namespace std;
int k, m, n, ok[1001][1001], vis[1001], cx[1001], cy[1001];
int dfs(int u){ // 从女生出发,扩充路径
fo(v,1,n){
if(ok[u][v] && !vis[v]){
vis[v] = 1;
if(cy[v]==-1 || dfs(cy[v])){
cy[v] = u; cx[u] = v;
return 1;
}
}
}
return 0;
}
// 打印匹配结果
void PP(){
fo(v,1,m){
if(cx[v]!=-1) printf("[%d, %d]\n", v,cx[v]);
}
}
ll maxmatch(){
ll ans = 0;
fo(u,1,m){ // 起点是女生,故最多有女生数量的路径数
memset(vis,0,sizeof(vis));
ans += dfs(u);
}
//PP();
return ans;
}
int main(){
scanf("%d", &k);
while(k){
scanf("%d%d",&m,&n);
memset(ok,0,sizeof(ok));
memset(cx,-1,sizeof(cx));
memset(cy,-1,sizeof(cy));
int t1,t2;
fo(i,1,k){
scanf("%d%d",&t1,&t2);
ok[t1][t2] = 1; // 女到男
}
printf("%lld\n",maxmatch());
scanf("%d", &k);
}
return 0;
}
2064 汉诺塔III
/*
f(n) 表示 从 a 到 c 的总数
f(n-1) 已求
那么f(n)则需要 n-1 个从a移动到c
第n个从a到b n-1 个又从c到a
第n个从b到c n-1 个又从a到c
共 2 + 3f(n-1) 次
故f(n) = 3f(n-1) + 2
推导公式:
f(n)+1 = 3(f(n-1)+1)
又首项 f(1) + 1 = 3
故f(n)+1 是以3为首项 公比为3的等比数列
故 f(n)+1 = 3^n
f(n) = 3^n -1
*/
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll m_pow(ll x, ll n){
ll res = 1;
while(n){
if(n&1) res *= x;
x *= x;
n >>= 1;
}
return res;
}
int main(){
int n;
while(scanf("%d",&n)!=EOF) printf("%lld\n", m_pow(3,n)-1);
}
2065 "红色病毒"问题 :https://blog.csdn.net/weixin_39778570/article/details/822561284
2066 一个人的旅行
#include<bits/stdc++.h>
#define fo(i, j, n) for(int i=j; i<=n; ++i)
#define ll long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 1005;
typedef pair<int, int> P;
struct edge{
int to, cost;
};
int V = 1000; // 顶点数
vector<edge> G[N];
int d[N];
void dijkstra(int s){
priority_queue< P, vector<P>, greater<P> > que;
fill(d, d+V+2, INF);
d[s] = 0;
que.push(P(0,s));
while(!que.empty()){
P p = que.top();
que.pop();
int v = p.second;
if(d[v] < p.first) continue; //到v点的距离如果已经被更新 这无须执行以下操作
for(auto e : G[v]){
if(d[e.to] > d[v]+e.cost){
d[e.to] = d[v] + e.cost;
que.push(P(d[e.to], e.to));
}
}
}
}
int T,S,D;
int main(){
int from, to, cost;
while(scanf("%d%d%d", &T,&S,&D) != EOF){
for(int i=0; i<N; i++) G[i].clear();
fo(i, 1, T){
scanf("%d%d%d",&from,&to,&cost);
edge var;
var.to = to; var.cost = cost;
G[from].push_back(var);
var.to = from; var.cost = cost;
G[to].push_back(var);
}
fo(i, 1, S){ // 多个地点问题
scanf("%d", &to);
edge var;
var.to = to; var.cost = 0;
G[0].push_back(var);
}
dijkstra(0);
int ans = INF;
fo(i,1,D){
scanf("%d", &to);
if(d[to]<ans) ans = d[to];
}
printf("%d\n", ans);
}
return 0;
}
2067 小兔的棋盘
/卡塔兰数,大数用java做/
C(2n , n)/( n+1 )
kf[i] = kf[i-1]*1.0/(i+1)*(4*i-2);
这条公数用来做大数的
Catalan[i] += Catalan[j] * Catalan[i - 1 - j];
小于35的数据
/*dp做法*/
#include<bits/stdc++.h>
#define fo(i,j,n) for(int i=j; i<=n; ++i)
#define ll long long
using namespace std;
int n;
ll dp[40][40];
void init(){
// 初始化第0行为1
fo(j, 0, 35) dp[0][j] = 1;
fo(j, 1, 35){ // 列
fo(i, 1, j){ // 行
if(i==j) dp[i][j] = dp[i-1][j];
else dp[i][j] = dp[i-1][j] + dp[i][j-1];
// printf("%d %d %lld\n", i, j, dp[i][j]);
}
printf("%lld\n",dp[j][j]);
}
}
int main(){
init();
int cnt=0;
while(scanf("%d", &n)&&n!=-1){
printf("%d %d %I64d\n", ++cnt, n, dp[n][n]*2);
}
}
import java.math.BigInteger;
import java.util.Scanner;
public class 卡塔兰数 {
static BigInteger[] kf = new BigInteger[40];
static void init() {
kf[1] = new BigInteger("1");
BigInteger one = new BigInteger("1");
BigInteger two = new BigInteger("2");
BigInteger four = new BigInteger("4");
for(int i=2; i<=35; ++i) {
String str = String.valueOf(i);
BigInteger n = new BigInteger(str);
kf[i] = (n.multiply(four).subtract(two)).multiply(kf[i-1]).divide(n.add(one));
}
for(int i=1; i<=35; i++) kf[i] = kf[i].multiply(two);
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int cnt = 0;
init();
while(sc.hasNext()) {
int n = sc.nextInt();
if(n==-1)break;
System.out.println(++cnt+" "+n+" "+kf[n].toString());
}
}
}
2068 RPG的错排
组合 + 错排
#include<bits/stdc++.h>
#define ll long long
#define fo(i, j, n) for(int i=j; i<=n; ++i)
using namespace std;
ll dd[30];
ll c[30][30];
void CC(){
c[0][0] = 1;
fo(i, 1, 25){
fo(j, 0, i){
if(j==0 || i==j) c[i][j] = 1;
else c[i][j] = c[i-1][j] + c[i-1][j-1];
// printf("%lld\n",c[i][j]);
}
}
}
void init(){
dd[0]=1, dd[1] = 0,dd[2] = 1; // dd[0]要设置成1因为下面要乘到
fo(i,3,25) dd[i] = (i-1)*(dd[i-1]+dd[i-2]);
// fo(i,1,25) printf("%I64d\n", dd[i]); 这里其实会溢出,但还AC了。。。
}
int main(){
init();
CC();
int n;
while(scanf("%d", &n)&&n!=0){
int mid = n >> 1; // 小于等于一半人
ll ans = 0;
fo(k,0,mid){
// printf("%d\n", k);
ans += c[n][k]*dd[k];
}
printf("%lld\n", ans);
}
return 0;
}
2069 Coin Change
硬币组合问题 dp
#include<bits/stdc++.h>
#define ll long long
#define fo(i, j, n) for(int i=j; i<=n; ++i)
using namespace std;
const int N = 300;
ll dp[300][105];
ll ans [300];
void init(){
dp[0][0] = 1;
int coins[5] = {50,25,10,5,1};
fo(k, 0, 4){ // 第几个硬币
fo(i, 1, 250){ // 钱数
fo(j, 1, min(100,i)){ // 硬币数,银币数不会大于钱数,最多100个硬币
if(i>=coins[k]) dp[i][j] += dp[i-coins[k]][j-1];
}
}
}
ans[0] = 1;
fo(i,1,250){
fo(j,0,min(100,i)) ans[i] += dp[i][j];
}
}
int main(){
init();
int n;
while(scanf("%d", &n)!=EOF){
printf("%lld\n", ans[n]);
}
return 0;
}
2070 Fibbonacci Number
#include<bits/stdc++.h>
#define ll long long
#define fo(i, j, n) for(int i=j; i<=n; ++i)
using namespace std;
ll fb[51];
void init(){
fb[0] = 0; fb[1] = 1;
fo(i,2,50){
fb[i] = fb[i-1] + fb[i-2];
// printf("%lld\n", fb[i]);
}
}
int main(){
init();
int n;
while(scanf("%d",&n) && n!=-1) printf("%lld\n", fb[n]);
return 0;
}
2071 Max Num
#include<bits/stdc++.h>
#define ll long long
#define fo(i, j, n) for(int i=j; i<=n; ++i)
using namespace std;
int t,n;
int main(){
scanf("%d",&t);
while(t--){
double a,max = 0.0;
scanf("%d", &n);
fo(i,1,n){
scanf("%lf", &a);
if(a>max)max=a;
}
printf("%.2f\n",max);
}
return 0;
}
2072 单词数
#include<bits/stdc++.h>
#define ll long long
#define fo(i, j, n) for(int i=j; i<=n; ++i)
using namespace std;
map<string,int> mp;
int main(){
string str,st;
while(getline(cin,str)&&str!="#"){
mp.clear();
stringstream ss(str);
while(ss>>st) mp[st]++;
printf("%d\n", mp.size());
}
return 0;
}
2073 无限的路
/注意数组开大点! 9999这个点要在线上,所以要开198至少*/
#include<bits/stdc++.h>
#define ll long long
#define fo(i, j, n) for(int i=j; i<=n; ++i)
using namespace std;
double d[100000],ans;
double dd[250][250];
void init(){
d[0] = 0.0, d[1] = 1.0;
dd[0][0] = 0, dd[0][1] = 1.0;
double m = sqrt(2);
int now = 2, k;
fo(i,1,200){
k = i;
fo(j,1,i){
d[now] = d[now-1] + m;
dd[j][--k] = d[now];
// cout << j << " " << k <<" "<< dd[j][k] << endl;
now++;
}
d[now] = d[now-1] + sqrt(i*i+(i+1)*(i+1)); // 注意啦,这里是从一排过度到另一排的斜线
dd[0][i+1] = d[now];
// cout << 0 << " " << i+1 << " " <<dd[0][i+1] << endl;
now++;
}
}
int n,x1,y1,x2,y2;
int main(){
init();
scanf("%d", &n);
while(n--){
scanf("%d%d%d%d", &x1,&y1,&x2,&y2);
ans = abs(dd[x1][y1]-dd[x2][y2]);
printf("%.3f\n", ans);
}
return 0;
}
2074 叠筐
#include<bits/stdc++.h>
#define ll long long
#define fo(i, j, n) for(int i=j; i<=n; ++i)
using namespace std;
char s[100][100];
void PP(int n, char a, char b){
if(n==1){printf("%c\n", a);return;}
memset(s,0,sizeof(s));
int mid = n/2;
s[mid][mid] = a;
int p = mid-1;
int q = mid+1;
char c = a;
while(p>=0){
if(c==a)c=b;else c=a;
s[mid][p--] = s[mid][q++] = c;
}
// printf("%s\n", s[mid]);
int k = 1;
c = a;
for(int i=mid-1; i>=0; --i){
strcpy(s[i], s[mid]);
p = mid-1;
q = mid+1;
if(c==a)c=b;else c=a;
s[i][mid]=c;
fo(j,1,k){
s[i][p--] = s[i][q++] = c;
}
k+=1;
// printf("%s\n", s[i]);
}
printf(" ");
fo(i,1,n-2) printf("%c",s[0][i]);
printf(" \n");
fo(i,1,mid) printf("%s\n",s[i]);
for(int i=mid-1; i>0; --i)printf("%s\n",s[i]);
printf(" ");
fo(i,1,n-2) printf("%c",s[0][i]);
printf(" \n");
}
int main(){
// PP(11,'B','A');
// PP(5,'@','W');
int n;
char a, b;
int flat = 0;
while(~scanf("%d %c %c",&n,&a,&b)){
if(flat) printf("\n");
else flat=1;
PP(n,a,b);
}
return 0;
}
2075 A|B?
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll T, a, b;
int main(){
cin >> T;
while(T--){
cin >> a >> b;
if(a%b==0) puts("YES");
else puts("NO");
}
return 0;
}
2076 夹角有多大(题目已修改,注意读题)
#include<bits/stdc++.h>
#define ll lnog long
#define fo(i, j ,n) for(int i=j; i<=n; ++i)
using namespace std;
int T, h, m, s;
int ans;
int main(){
scanf("%d", &T);
while(T--){
scanf("%d%d%d", &h,&m,&s);
if(h>=12) h-=12; // 注意不是24小数制的哈
double m1 = m + 1.0*s / 60;
double t1 = h*5 + m1/12;
double d = abs(t1-m1);
double dd = min(d, 60-d);
ans = dd*6/1;
printf("%d\n", ans);
}
return 0;
}
2077 汉诺塔IV
n-1个到第二个柱子,n(最大)个到第2个柱子再到第3个柱子,n-1和从第二个柱子到第三个柱子
f(n) = 3^n-1 -1 + 2 = 3^n-1 + 1
#include<bits/stdc++.h>
#define ll long long
#define fo(i, j ,n) for(int i=j; i<=n; ++i)
using namespace std;
ll pow_mod(ll x, ll n){
ll res = 1;
while(n){
if(n&1) res *= x;
x *= x;
n >>= 1;
}
// cout << res << endl;
return res;
}
int T,n;
ll ans;
int main(){
scanf("%d", &T);
while(T--){
scanf("%d", &n);
ans = pow_mod(3,n-1) + 1;
printf("%I64d\n", ans);
}
return 0;
}
2078 复习时间
#include<bits/stdc++.h>
#define ll long long
#define fo(i, j, n) for(int i=j; i<=n; ++i)
using namespace std;
int t,a[50],ans;
int main(){
scanf("%d",&t);
while(t--){
memset(a,0,sizeof(a));
int n,m;
scanf("%d %d", &n,&m);
fo(i,0,n-1) scanf("%d", &a[i]);
sort(a,a+n);
ans = (100-a[0])*(100-a[0]);
printf("%d\n",ans);
}
return 0;
}
2079 选课时间
/组合问题 母函数模板/
/*
a保存结果,b中间结果
v权值 n1初始数量 n2终止数量
*/
#include<bits/stdc++.h>
#define ll long long
#define fo(i, j, n) for(int i=j; i<=n; ++i)
using namespace std;
int t,n,k,last,last2;
int a[1000],b[1000];
int v[10],n2[10]; // 权值,终止数量
int main(){
scanf("%d", &t);
while(t--){
scanf("%d%d", &n,&k);
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(v,0,sizeof(v));
memset(n2,0,sizeof(n2));
fo(i, 0, k-1) scanf("%d %d", &v[i], &n2[i]);
a[0]=1;
last = 0;
fo(i,0,k-1){ // 第i个括号
last2 = last + n2[i]*v[i]; // 目前最远项
memset(b,0,sizeof(int)*(last2+1));
for(int j=0; j<=n2[i]; j++){ // 遍历第i个括号的每一项
for(int k=0; k<=last; k++){ // 遍历a的每一项
b[k+j*v[i]] += a[k];
}
}
memcpy(a,b,sizeof(int)*(last2+1));
last = last2;
}
printf("%d\n", a[n]);
}
return 0;
}
2080 夹角有多大II
#include<bits/stdc++.h>
#define ll long long
#define PI 3.141592
using namespace std;
int t;
double x1,y1,x2,y2;
double a2, b2, c2, cosC, ans;
int main(){
scanf("%d",&t);
while(t--){
scanf("%lf %lf %lf %lf", &x1,&y1,&x2,&y2);
a2 = x1*x1+y1*y1;
b2 = x2*x2+y2*y2;
// cout<< a2 << "\n" << b2<<endl;
c2 = (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2);
cosC = (a2+b2-c2)/(2*sqrt(a2)*sqrt(b2));
// cout << cosC << endl;
ans = acos(cosC)*180/PI;
printf("%.2f\n",ans);
}
return 0;
}