The 2016 ACM-ICPC Asia China-Final (Shanghai) Contest---重現賽題解
題意:
Mr. Panda is one of the top specialists on number theory all over the world. Now Mr. Panda is investigating the property of the powers of 2. Since 7 is the lucky number of Mr. Panda, he is always interested in the number that is a multiple of 7. However, we know that there is no power of 2 that is a multiple of 7, but a power of 2 subtracted by one can be a multiple of 7. Mr. Panda wants to know how many positive integers less than 2 N in the form of 2 k − 1 (k is a positive integer) that is divisible by 7. N is a positive interger given by Mr Panda.
Input
The first line of the input gives the number of test cases, T. T test cases follow. Each test case contains only one positive interger N.
Output
For each test case, output one line containing ‘Case #x: y’, where x is the test case number (starting from 1) and y is the answer. Limits: • 1 ≤ T ≤ 100. • 1 ≤ N ≤ 105 .
思路:一開始用java的大數直接預處理算的,結果T了,,,可能是大數太大造成超時,後來隊友發現規律,,,每3
個+1,,用C++也一樣。。
程式碼:
import java.math.BigInteger; import java.util.*; public class Main { public static void main(String args[]) { Scanner cin = new Scanner(System.in); int n,T,cas=0; int num[]=new int[100005]; num[1]=num[2]=num[0]=0; int res=1; for(int i=3;i<=100000;i+=3) { num[i+0]=res; num[i+1]=res; num[i+2]=res; res++; } T=cin.nextInt(); while(T-->0) { n=cin.nextInt(); System.out.println("Case #"+(++cas)+": " + num[n]); } cin.close(); } }
題意:
Here is World Cup again, the top 32 teams come together to fight for the World Champion. The teams are assigned into 8 groups, with 4 teams in each group. Every two teams in the same group will play a game (so there are totally 6 games in each group), and the winner of this game gets 3 points, loser gets 0 point. If it is a tie game, both teams get 1 point. After all games finished, we get the scoreboard, but we forget the result of each game, can you help us to figure the result of each game? We only care about the win/lose/tie result of each game, but we don’t care the goals in each game.
Input
The input starts with one line containing exactly one integer T, which is the number of test cases. Each test case contains four space-separated integers A, B, C, D, in a line, which indicate the points each team gets after all 6 games.
Output
For each test case, output one line containing ‘Case #x: y’, where x is the test case number (starting from 1) and y is ‘Yes’ if you can point out the result of each game, or ‘No’ if there are multiple game results satisfy the scoreboard, or ‘Wrong Scoreboard’ if there is no game result matches the scoreboard. Limits: • 1 ≤ T ≤ 100. • 0 ≤ A, B, C, D ≤ 100.
Notes:In sample case #1, the only scenaro will be: the first team wins all the three games it plays, the second team loses to the first team and wins the other two, the third team only wins the game with the fourth, and the fourth team lose all the games. In sample case #2, the fourth team loses all the games, and the first three teams get into a winningcycle, but there may be two different winning-cycles: first team wins second team, second team wins third team, third team wins first team OR first team wins third team, third team wins second team, second team wins first team. We can’t figure which winning-cycle is the actual game result. In sample case #3, the first team get 10 points, but no team could get more than 9 points by play three games, so it is a wrong scoreboard.
思路:dfs枚舉出所有可能情況的結果,然後根據輸入一一比對,然後判斷輸出就可以了
程式碼:
#include <bits/stdc++.h>
using namespace std;
int cas,T,a[10],ans,pp[10000][10],ss,ok,t;
int x[10]={0,1,1,1,2,2,3},y[10]={0,2,3,4,3,4,4},sum[10];
int dfs(int c,int v)
{//cout<<c<<" "<<v<<endl;
if(c==7) {//t++;//cout<<t<<"!!"<<endl;
ss++;
for(int i=1;i<=4;i++)
{
pp[ss][i]=sum[i];
// cout<<
}
return 0;
}
sum[x[c]]+=3;
dfs(c+1,v+1);
sum[x[c]]-=3;
sum[y[v]]+=3;
dfs(c+1,v+1);
sum[y[v]]-=3;
sum[x[c]]+=1;
sum[y[v]]+=1;
dfs(c+1,v+1);
sum[x[c]]-=1;
sum[y[v]]-=1;
return 0;
}
int main()
{
scanf("%d",&T);
// cout<<pow(3,6)<<endl;
dfs(1,1);
//cout<<ss<<endl;
while(T--)
{
cas++;
ans=0;
for(int i=1;i<=4;i++)
scanf("%d",&a[i]);
for(int i=1;i<=ss;i++)
{
ok=1;
for(int j=1;j<=4;j++)
{
if(pp[i][j]!=a[j]) {ok=0;break;}
}
if(ok) ans++;
}
printf("Case #%d: ",cas);
if(ans==0) printf("Wrong Scoreboard\n");
else if(ans==1) printf("Yes\n");
else printf("No\n");
}
}
題意:
Mr. Panda likes ice cream very much especially the ice cream tower. An ice cream tower consists of K ice cream balls stacking up as a tower. In order to make the tower stable, the lower ice cream ball should be at least twice as large as the ball right above it. In other words, if the sizes of the ice cream balls from top to bottom are A0, A1, A2, · · · , AK−1, then A0 × 2 ≤ A1, A1 × 2 ≤ A2, etc. One day Mr. Panda was walking along the street and found a shop selling ice cream balls. There are N ice cream balls on sell and the sizes are B0, B1, B2, · · · , BN−1 . Mr. Panda was wondering the maximal number of ice cream towers could be made by these balls.
Input
The first line of the input gives the number of test cases, T. T test cases follow. Each test case starts with a line consisting of 2 integers, N the number of ice cream balls in shop and K the number of balls needed to form an ice cream tower. The next line consists of N integers representing the size of ice cream balls in shop.
Output
For each test case, output one line containing ‘Case #x: y’, where x is the test case number (starting from 1) and y is the maximal number of ice cream towers could be made. Limits: • 1 ≤ T ≤ 100. • 1 ≤ N ≤ 3 × 105 . • 1 ≤ K ≤ 64. • 1 ≤ Bi ≤ 1018 .
思路:二分答案,對於每個mid判是否能構成mid個k層的ice。判斷方法是,在所有冰淇淋上一層一層的從小到大加。
先給每個冰淇淋的第一層依次都放上,然後在依次放合法的到第二層。。。直到第k層。
對於小的下面放大的球,若兩個冰淇淋的第一層是a b。a<b,對於cd球,若a下是d,b下是c,成立,那麼a下是c,b下是d一定成立,所以要構成mid個k個球的冰淇淋,一定可以從小球開始,一層一層的球到每個冰淇淋上。每一層,每個冰淇淋的球的相對大小一致。
程式碼:
#include <bits/stdc++.h>
using namespace std;
int cas,T,n,k,top[100],s;
long long a[300010];
int AA(int num)
{
int no=1,f=0;
for(int i=1;i<=num;i++)
top[i]=a[i];
s=num+1;
while(1)
{
f=0;
for(int i=1;i<=num;i++)
{
while(a[s]<top[i]*2&&s<=n)
{
s++;
}
top[i]=a[s];
s++;f++;
if(s>n) break;
}
if(f==num) no++;
if(no>=k) return 1;
if(n-s+1<(k-no)*num) return 0;
}
return 0;
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&k);
cas++;
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
sort(a+1,a+1+n);
int l=0,r=n/k+1,mid=-1;
while(1)
{
if(mid==(l+r)/2) break;
mid=(l+r)/2;
if(AA(mid)) l=mid;
else r=mid;
}
printf("Case #%d: %d\n",cas,l);
}
}
題意:
Mr. Panda likes playing puzzles with grid paper. Recently he invented a new rule to play with the grid paper. At the beginning, he grabs a grid paper with N rows and M columns. Then he fills each cell an integer in the range of [1, K]. After filling all the cells, he starts finding Great cells in the grid. A cell is called Great cell if and only if it meets the following 2 conditions: • The value in the cell is strictly larger than other cells in the same row. • The value in the cell is strictly larger than other cells in the same column. Now Mr. Panda is wondering how many different ways he can fill the grid paper so that there are exactly g Great cells. As Mr. Panda likes simple conclusion number, let’s just tell him the value NM ∑ g=0 (g + 1) · Ag mod (109 + 7) Ag represents the number of different ways Mr. Panda can fill the grid paper such that there are exactly g Great cells.
Input
The first line of the input gives the number of test cases, T. T lines follow. Each line represents a test case containing 3 integers N, M representing the number of rows and columns of the grid paper, K representing the range for filling numbers.
Output
For each test case, first output one line containing ‘Case #x: y’, where x is the test case number (starting from 1), y is the simple conclusion number for Mr. Panda. Limits: • 1 ≤ T ≤ 20. • 1 ≤ N, M, K ≤ 200. Note: For the first sample, A0 = 10, A1 = 4, A2 = 2, A3 = A4 = 0, thus the answer is 10+4×2+2×3 = 24.
思路:換個思路,推公式。把括號拆出來,就是所有情況數 。可以理解為,所有位置是好數的次數和,然後就推一下公式就可以了。
每個位置是好數的次數都相等//*(nm),對於每個位置,是好數可以取的值(i+1)是在[2,k]範圍,一行一列的其他位置是可以取[1,i],就是,非同行同列的其他 nm-n-m+1給格子[1,k]隨便取值.
最後公式是
程式碼:
#include <bits/stdc++.h>
using namespace std;
#define mod 1000000007
typedef long long ll;
inline ll fpow(ll n,ll k)
{
ll res=1;
while(k>0)
{
if(k&1)
res=res*n%mod;
n=n*n%mod;
k>>=1;
}
return res;
}
inline ll solve(ll k,ll p)
{
ll res=0;
for(ll i=1;i<=k-1;i++)
{
res+=fpow(i,p);
res%=mod;
}
return res;
}
int N,M,K,T,cas;
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&N,&M,&K);
cas++;
ll ans=0;
ans=solve(K,N+M-2);
ans*=fpow(K,N*M-N-M+1);
ans%=mod;
ans*=N*M;
ans%=mod;
ans+=fpow(K,N*M);
ans%=mod;
printf("Case #%d: %lld\n",cas,ans);
}
}
題意:
The Codejamon game is on fire! Fans across the world are predicting and betting on which team will win the game. A gambling company is providing betting odds for all teams; the odds for the i-th team is Ai : Bi . For each team, you can bet any positive amount of money, and you do not have to bet the same amount on each team. If the i-th team wins, you get your bet on that team back, plus Bi Ai times your bet on that team. For example, suppose that there are two teams, with odds of 5:3 and 2:7 and you bet $20 on the first team and $10 on the second team. If the first team wins, you will lose your $10 bet on the second team, but you will receive your $20 bet back, plus 3 5 × 20 = 12, so you will have a total of $32 at the end. If the second team wins, you will lose your $20 bet on the first team, but you will receive your $10 bet back, plus 7 2 × 10 = 35, so you will have a total of $45 at the end. Either way, you will have more money than you bet ($20+$10=$30). As a greedy fan, you want to bet on as many teams as possible to make sure that as long as one of them wins, you will always end up with more money than you bet. Can you figure out how many teams you can bet on?
Input
The input starts with one line containing exactly one integer T, which is the number of test cases. Each test case starts with one line containing an integer N: the number of teams in the game. Then, N more lines follow. Each line is a pair of numbers in the form ‘Ai:Bi ’ (that is, a number Ai , followed by a colon, then a number Bi , with no spaces in between), indicating the odds for the i-th team.
Output
For each test case, output one line containing ‘Case #x: y’, where x is the test case number (starting from 1) and y is the maximum number of teams that you can bet on, under the conditions specified in the problem statement. Limits: • 1 ≤ T ≤ 100. • 1 ≤ N ≤ 100. • 0 < Ai , Bi < 100. • Both Ai and Bi have at most 3 digits after the decimal point.
Note: In sample case #1, one optimal strategy is to bet 1.5 dollars on the first team and 1.5 dollars on the third team. If the first team wins, you will get 1.5 + 1.5 × (1.1/1) = 3.15 dollars back, and if the third team wins, you will get 1.5 + (1.7/1.5) × 1.5 = 3.2 dollars back. Both of these are higher than the total money that you bet (1.5 + 1.5 = 3 dollars). However, there is no way to bet on all three teams and be guaranteed a profit.
思路:簡單轉化一下公式,據說是個高精度的題,但是long double也能過
令xi為投注第i個的成本, 即:
要數量最多,那麼要儘量小,所以就按小的排序。一直加到>1就停下。
程式碼:
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const int maxn=100+10;
long double p[maxn];
int main()
{
int cas;
scanf("%d",&cas);
for(int k=1;k<=cas;k++)
{
int n;
scanf("%d",&n);
long double x,y;
char ch;
rep(i,1,n+1)
{
cin>>x>>ch>>y;
long double x1=(x*1000),y1=(y*1000);
p[i]=1.0*x1/(long double)(x1+y1);
}
long double sum=0;
sort(p+1,p+n+1);
int cnt=0;
rep(i,1,n+1)
{
sum+=p[i];
if(sum>=1) break;
cnt++;
}
printf("Case #%d: %d\n",k,cnt);
}
return 0;
}