题目描述
小明同学喜欢体育锻炼,他常常去操场上跑步。跑道是一个圆形,在本题中,我们认为跑道是一个半径为R的圆形,设圆心的坐标为原点(0,0)。
小明跑步的起点坐标为(R,0),他沿着圆形跑道跑步,而且一直沿着一个方向跑步。回到家后,他查看了自己的计步器,计步器显示他跑步的总路程为L。
小明想知道自己结束跑步时的坐标,但是他忘记自己是沿着顺时针方向还是逆时针方向跑的了。他想知道在这两种情况下的答案分别是多少。
题目解析:
我们都知道, L=Rθ ,那么求出 θ 来, x=rcosθ,y=rsinθ 就好了。再把y反过来
#include
using namespace std;
#define RE(x) freopen(x,"r",stdin)
#define WR(x) freopen(x,"w",stdout)
#define INF 0x3f3f3f3f
#define CLEAR(x) memset(x,0,sizeof(x))
#define pb push_back
#define mp make_pair
typedef long long ll;
typedef vector<int> vi;
typedef vector vl;
typedef pair<int,int> pii;
const int M = 1e9+7;
const double PI = acos(-1.0);
const double eps = 1e-8;
int main() {
//RE("in.txt");WR("out.txt");
int l,r;
cin>>l>>r;
double theta = l*1.0/r;
double x=r*cos(theta),y=r*sin(theta);
printf("%.3lf %.3lf\n%.3lf %.3lf\n",x,-y,x,y);
}
题目描述
小明买了一些彩色的气球用绳子串在一条线上,想要装饰房间,每个气球都染上了一种颜色,每个气球的形状都是各不相同的。我们用1到9一共9个数字表示不同的颜色,如12345则表示一串5个颜色各不相同的气球串。但小明希望得到不出现重复颜色的气球串,那么现在小明需要将这个气球串剪成多个较短的气球串,小明一共有多少种剪法?如原气球串12345的一种是剪法是剪成12和345两个气球串。
注意每种剪法需满足最后的子串中气球颜色各不相同(如果满足该条件,允许不剪,即保留原串)。两种剪法不同当且仅当存在一个位置,在一种剪法里剪开了,而在另一种中没剪开。详见样例分析。
题目解析
其实这题的意思就是,把一个数组切成若干子数组,要求每一段里面都没有重复数字,问有多少切法。
观察到一共就9种数字,且第i个数字只与最后一段有关系,考虑 状压dp。令dp[i][s]表示前i个数,最后一串的状态为s的切法。那么,最终答案可表示为:
转移方程写对了,代码自然是水到渠成。
Question: 标程的解法看起来像O(n^2)的,为什么比我的快?
#include
using namespace std;
#define RE(x) freopen(x,"r",stdin)
#define WR(x) freopen(x,"w",stdout)
#define INF 0x3f3f3f3f
#define CLEAR(x) memset(x,0,sizeof(x))
#define pb push_back
#define mp make_pair
typedef long long ll;
typedef vector<int> vi;
typedef vector vl;
typedef pair<int,int> pii;
const int M = 1e9+7;
const double PI = acos(-1.0);
const double eps = 1e-8;
int n;
int a[100005];
int dp[100005][513];
int main() {
//RE("in.txt");WR("out.txt");
cin>>n;
for(int i=1;i<=n;i++) {
cin>>a[i];
}
dp[1][1<<(a[1]-1)]=1;
for(int i=2;i<=n;i++) {
int s=1<<(a[i]-1);
for(int j=1;j<=512;j++) {
dp[i][s]+=dp[i-1][j];
dp[i][s]%=M;
if(!(s&j))
dp[i][s|j]=dp[i-1][j];
}
}
ll ans=0;
for(int i=1;i<=512;i++) {
ans+=dp[n][i];
}
cout<
题目描述
A、B两伙马贼意外地在一片沙漠中发现了一处金矿,双方都想独占金矿,但各自的实力都不足以吞下对方,经过谈判后,双方同意用一个公平的方式来处理这片金矿。处理的规则如下:他们把整个金矿分成n段,由A、B开始轮流从最左端或最右端占据一段,直到分完为止。
马贼A想提前知道他们能分到多少金子,因此请你帮忙计算他们最后各自拥有多少金子?(两伙马贼均会采取对己方有利的策略)
题目解析:
这道题临场的时候没看懂题意,直接交卷了QAQ.
就是给你n段数,A,B两人轮流选择,可以选最左的或者最右的,每次都选择对己方最有利的策略。问AB最后各有多少金子?
令dp[i][j]表示当前还剩的金矿是区间[i,j]时,A取得的最大收益。这个转移要考虑此时该A拿还是该B拿。
如果该A拿,则有dp[i][j]=max(dp[i+1][j]+a[i],dp[i][j-1]+a[j]);
如果该B拿,则有dp[i][j]=min(dp[i+1][j],dp[i][j-1]);
,因为B拿哪边都不会增加A的收益,而他要使A尽量拿的小。
那么如何判断该A拿还是该B拿呢,这就与n和区间长度的奇偶关系有关了。观察到,如果n是偶数,则区间长度是偶数时轮到A拿,否则轮到B拿,n是奇数反之。所以该谁拿取决于n和当前区间长度的奇偶关系。在这里因为大区间只依赖于长度比他小1的小区间,所以自底向上枚举区间长度即可。
#include
using namespace std;
#define RE(x) freopen(x,"r",stdin)
#define WR(x) freopen(x,"w",stdout)
#define INF 0x3f3f3f3f
#define CLEAR(x) memset(x,0,sizeof(x))
#define pb push_back
#define mp make_pair
typedef long long ll;
typedef vector<int> vi;
typedef vector vl;
typedef pair<int,int> pii;
const int M = 1e9+7;
const double PI = acos(-1.0);
const double eps = 1e-8;
int dp[555][555];
int T,n;
int a[555];
int main() {
//RE("in.txt");WR("out.txt");
cin>>T;
for(int i=1;i<=T;i++) {
cin>>n;
int sum = 0;
for(int i=0;icin>>a[i];
sum+=a[i];
}
memset(dp,0,sizeof(dp));
//dfs(0,n-1,1);
if(n&1) {
for(int i=0;ifor(int i=1;ifor(int j=0;j+iif(((n+i)&1)==0) {
dp[j][j+i]=min(dp[j+1][j+i],dp[j][j+i-1]);
}
else {
dp[j][j+i]=max(dp[j+1][j+i]+a[j],dp[j][j+i-1]+a[j+i]);
}
}
}
cout<<"Case #"<": "<0][n-1]<<" "<0][n-1]<