骰⼦的游戏
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
在Alice和Bob面前的是两个骰子,上面分别写了六个数字。
Alice和Bob轮流丢掷骰子,Alice选择第一个骰子,而Bob选择第二个,如果谁投掷出的数更大,谁就可以获胜。
现在给定这两个骰子上的6个数字,你需要回答是Alice获胜几率更大,还是Bob获胜几率更大。(请注意获胜几率相同的情况)
输入描述:
第一行一个数T,表示数据个数。
接下来的每一组数据一共有2行,每一行有6个正整数,第一行是第一个骰子上的6个数,第二行是第二个骰子上的6个数。
输出描述:
如果Alice获胜几率更大,你需要输出Alice;
如果Bob获胜几率更大,你需要输出Bob;
如果获胜几率一样大,你需要输出Tie。
示例1
输入
2 3 3 3 3 3 3 1 1 4 4 4 4 1 2 3 4 5 6 6 5 4 3 2 1
输出
Bob Tie
说明
第一个数据中,Alice有三分之一几率获胜,Bob有三分之二几率获胜;
第二个数据中,Alice和Bob的骰子完全一致,所以获胜几率一样大。
备注:
对于30%的数据,1 ≤ T ≤ 10。
对于60%的数据,1 ≤ T ≤ 1000。
对于100%的数据,1 ≤ T ≤ 10^5,所有输入的数均 ≤ 10^7。
直接比较大小就可以了
#include<bits/stdc++.h> using namespace std; int main() { int n,a[10],b[10]; scanf("%d",&n); while(n--) { for(int i=0; i<6; i++) scanf("%d",&a[i]); for(int i=0; i<6; i++) scanf("%d",&b[i]); int s=0,t=0; for(int i=0; i<6; i++) for(int j=0; j<6; j++) { if(a[i]>b[j])s++; if(a[i]<b[j])t++; } if(s==t)puts("Tie"); else if(s>t)puts("Alice"); else puts("Bob"); } return 0; }
以下代码适合a,b数组特别大的时候
nlogn解决这个a数组大于b数组的个数,无法更快解决吧,感觉两个指针可以把有序数组这个优化下
#include<bits/stdc++.h> using namespace std; int main() { int n,a[10],b[10]; scanf("%d",&n); while(n--) { for(int i=0; i<6; i++) scanf("%d",&a[i]); for(int i=0; i<6; i++) scanf("%d",&b[i]); sort(a,a+6); sort(b,b+6); int s=0,t=0; for(int i=0;i<6;i++) s+=lower_bound(a,a+6,b[i])-a; for(int i=0;i<6;i++) t+=lower_bound(b,b+6,a[i])-b; if(s==t)puts("Tie"); else if(s<t)puts("Alice"); else puts("Bob"); } return 0; }
我想的尺取贪心写不大出来,感觉二分够了,顶多加个离散化
购物
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
在遥远的东方,有一家糖果专卖店。
这家糖果店将会在每天出售一些糖果,它每天都会生产出m个糖果,第i天的第j个糖果价格为C[i][j]元。
现在的你想要在接下来的n天去糖果店进行选购,你每天可以买多个糖果,也可以选择不买糖果,但是最多买m个。(因为最多只生产m个)买来糖果以后,你可以选择吃掉糖果或者留着之后再吃。糖果不会过期,你需要保证这n天中每天你都能吃到至少一个糖果。
这家店的老板看你经常去光顾这家店,感到非常生气。(因为他不能好好睡觉了)于是他会额外的要求你支付点钱。具体来说,你在某一天购买了 k 个糖果,那么你在这一天需要额外支付 k2 的费用。
那么问题来了,你最少需要多少钱才能达成自己的目的呢?
输入描述:
第一行两个正整数n和m,分别表示天数以及糖果店每天生产的糖果数量。
接下来n行(第2行到第n+1行),每行m个正整数,第x+1行的第y个正整数表示第x天的第y个糖果的费用。
输出描述:
输出只有一个正整数,表示你需要支付的最小费用。
示例1
输入
3 2 1 1 100 100 10000 10000
输出
107
示例2
输入
5 5 1 2 3 4 5 2 3 4 5 1 3 4 5 1 2 4 5 1 2 3 5 1 2 3 4
输出
10
备注:
对于100%的数据,1 ≤ n, m ≤ 300 , 所有输入的数均 ≤ 106。
dp,前i天买x个最小花费
#include<bits/stdc++.h> using namespace std; vector<int>V[305]; int dp[305][305],a[305][305]; int main() { int n,m; scanf("%d%d",&n,&m); for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++) { int x; scanf("%d",&x); V[i].push_back(x); } sort(V[i].begin(),V[i].end()); for(int j=1; j<=m; j++) a[i][j]=a[i][j-1]+V[i][j-1]; } memset(dp,-1,sizeof dp); dp[0][0]=0; for(int i=1; i<=n; i++) for(int j=i; j<=n; j++) { for(int k=0; k<=j&&k<=m; k++) { if(dp[i-1][j-k]!=-1) { if(dp[i][j]!=-1)dp[i][j]=min(dp[i-1][j-k]+a[i][k]+k*k,dp[i][j]); else dp[i][j]=dp[i-1][j-k]+a[i][k]+k*k; } } } printf("%d",dp[n][n]); return 0; }
珂朵莉的数列
时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld
题目描述
珂朵莉给了你一个序列,有个子区间,求出她们各自的逆序对个数,然后加起来输出
输入描述:
第一行一个数 n 表示这个序列 a 的长度
之后一行 n 个数,第i个数表示ai
输出描述:
输出一行一个数表示答案
示例1
输入
10 1 10 8 5 6 2 3 9 4 7
输出
270
示例2
输入
20 6 0 4 5 8 8 0 6 6 1 0 4 6 6 0 0 7 2 0 5
输出
3481
备注:
对于100%的数据,n <=
1000000 ,0 <= 序列中每个数 <= 1000000000
树状数组+二维pair算贡献去求
但是爆了ll
#include<bits/stdc++.h> using namespace std;; typedef long long ll; const int N=1e6+5; int n,cnt=1,a[N]; pair<int,int> t[N]; ll c[N]; string add(string s1,string s2){ string s; int len1,len2; len1=s1.size()-1; len2=s2.size()-1; int i=0,f=0; while(len1>-1&&len2>-1){ int sum=f+(s1[len1--]-'0')+(s2[len2--]-'0'); s+=sum%10+'0'; f=sum/10; } while(len1>-1){ int sum=f+(s1[len1--]-'0'); s+=sum%10+'0'; f=sum/10; } while(len2>-1){ int sum=f+(s2[len2--]-'0'); s+=sum%10+'0'; f=sum/10; } if(f) s+='0'+f; reverse(s.begin(),s.end()); return s; } void add(int k,int x) { while(k>=1) { c[k]+=x; k-=(k&-k); } } ll query(int k) { ll ans=0; while(k<=cnt) { ans+=c[k]; k+=(k&-k); } return ans; } void solve() { string ans="0"; for(int i=1; i<=n; i++) { ll x=query(a[i]+1)*1LL*(n-i+1); string c1=""; if(x==0)c1+="0"; while(x) { c1+=x%10+'0'; x=x/10; } reverse(c1.begin(),c1.end()); ans=add(ans,c1); add(a[i],i); } cout<<ans<<endl; } int main() { scanf("%d",&n); for(int i=1; i<=n; i++) { scanf("%d",&a[i]); t[i]=make_pair(a[i],i); } sort(t+1,t+n+1); for(int i=1; i<=n; i++) { if(t[i-1].first!=t[i].first) { cnt++; } a[t[i].second]=cnt; } solve(); return 0; }
__int128写法
#include<bits/stdc++.h> using namespace std;; typedef long long ll; const int N=1e6+5; int n,cnt=1,a[N]; pair<int,int> t[N]; ll c[N]; void print(__int128 x) { if (x==0) return; if (x) print(x/10); putchar(x%10+'0'); } void add(int k,int x) { while(k>=1) { c[k]+=x; k-=(k&-k); } } ll query(int k) { ll ans=0; while(k<=cnt) { ans+=c[k]; k+=(k&-k); } return ans; } void solve() { __int128 ans=0; for(int i=1; i<=n; i++) { ans+=query(a[i]+1)*1LL*(n-i+1); add(a[i],i); } if(ans==0)putchar('0'); print(ans); } int main() { scanf("%d",&n); for(int i=1; i<=n; i++) { scanf("%d",&a[i]); t[i]=make_pair(a[i],i); } sort(t+1,t+n+1); for(int i=1; i<=n; i++) { if(t[i-1].first!=t[i].first)cnt++; a[t[i].second]=cnt; } solve(); return 0; }