牛客-常州大学新生寒假训练会试
2018-02-08 14:40
363 查看
A.添加逗号
题目描述
对于一个较大的整数 N(1<=N<=2,000,000,000) 比如 980364535,我们常常需要一位一位数这个数字是几位数,但是如果在这 个数字每三位加一个逗号,它会变得更加易于朗读。 因此,这个数字加上逗号成如下的模样:980,364,535请写一个程序帮她完成这件事情输入描述:
一行一个整数 N
输出描述:
一行一个字符串表示添加完逗号的结果思路:一眼签到题 直接上代码
[cpp] view plain copy print?#include <iostream>
#include <cstring>
#include <set>
#include <map>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1e6+11;
int prime[maxn],cnt;
bool is_prime[maxn];
int main(){
ll n;
char str[15];
char ans[20];
while(cin>>str){
int len = strlen(str);
int cnt = 0;
int a_c = 0;
for(int i=len-1;i>=0;i--){
ans[a_c++] = str[i];
cnt++;
if(cnt==3){
if(i==0) break;
ans[a_c++] = ',';
cnt = 0;
}
}
for(int i=a_c-1;i>=0;i--) cout<<ans[i];
cout<<endl;
}
}
#include <iostream> #include <cstring> #include <set> #include <map> #include <vector> #include <algorithm> using namespace std; typedef long long ll; const int maxn = 1e6+11; int prime[maxn],cnt; bool is_prime[maxn]; int main(){ ll n; char str[15]; char ans[20]; while(cin>>str){ int len = strlen(str); int cnt = 0; int a_c = 0; for(int i=len-1;i>=0;i--){ ans[a_c++] = str[i]; cnt++; if(cnt==3){ if(i==0) break; ans[a_c++] = ','; cnt = 0; } } for(int i=a_c-1;i>=0;i--) cout<<ans[i]; cout<<endl; } }
B.对称
题目描述
萌新AA喜欢对称,最近她喜欢把棋子放进她的棋盘中,这个棋盘是由 N×M 个格 子构成的(1 <= N <= 1,000,000,000;1<=M<=1,000,000,000) 为了保证对称,AA 会以这样的方式摆放她的棋子。她把棋子放在棋盘正中央的方格内, 如果不存在这样的方格,她就会停止。然后她以这个方格为中心把棋盘分成四部分,然后对于每 个小棋盘进行上述的操作。 下面是一个 N=7,M=15 的例子,其中'C'表示棋子这样子,需要 21个棋子。如果 N=M=5 的话,AA只需要摆放一个棋子,因为分成的四 个小棋盘分别是 2×2 的大小,无法在放进去新的棋子。现在,请你帮助 AA来计算,需要 多少个棋子。
输入描述:
一行两个整数 N,M
输出描述:
一行一个整数,即需要的棋子数思路:只有n和m是奇数时才能分成4部分.
比如样例 n=7 m=15
第一次 : n%2==1 m%2==1 时可以拆的 ,这次放置了1个棋子
第二次: (n/2)%2==1 (m/2)%2==1 也满足,这次放了4个棋子
第三次 ....... 这次放了16个棋子
你会发现 其实是个等比数列,公比是4
只要我们求出 n(即能拆多少次)就能求出等比数列和
不过这里注意一个坑点,就是当n==1||m==1时 ans=1;
[cpp] view plain copy print?#include <iostream>
#include <stdio.h>
#include <cstring>
#include <set>
#include <map>
#include <vector>
#include <algorithm>
using namespace std;
typedef unsigned long long ll;
const int maxn = 1e6+11;
int prime[maxn],cnt;
bool is_prime[maxn];
struct qwe{
int h,m,s;
}q[5015];
ll q_mod(ll x,ll n){
ll res = 1;
while(n){
if(n&1) res =res*x;
x = x*x;
n>>=1;
}
return res;
}
int main(){
ll n,m;
while(scanf("%lld%lld",&n,&m)!=EOF){
ll cnt = 0;
ll ans = 0;
if((n==1&&m!=1)||(n!=1&&m==1)){
cout<<"1"<<endl;
}else{
while((n%2==1)&&(m%2==1)){
cnt++;
if(n==1||m==1) break;
n/=2;
m/=2;
}
ans += (q_mod(4,cnt)-1)/3;
printf("%lld\n",ans);
}
}
return 0;
}
#include <iostream> #include <stdio.h> #include <cstring> #include <set> #include <map> #include <vector> #include <algorithm> using namespace std; typedef unsigned long long ll; const int maxn = 1e6+11; int prime[maxn],cnt; bool is_prime[maxn]; struct qwe{ int h,m,s; }q[5015]; ll q_mod(ll x,ll n){ ll res = 1; while(n){ if(n&1) res =res*x; x = x*x; n>>=1; } return res; } int main(){ ll n,m; while(scanf("%lld%lld",&n,&m)!=EOF){ ll cnt = 0; ll ans = 0; if((n==1&&m!=1)||(n!=1&&m==1)){ cout<<"1"<<endl; }else{ while((n%2==1)&&(m%2==1)){ cnt++; if(n==1||m==1) break; n/=2; m/=2; } ans += (q_mod(4,cnt)-1)/3; printf("%lld\n",ans); } } return 0; }
C.竞赛技巧
题目描述
在ACM竞赛中,当遇到有两个队伍(人) 解出相同的题目数量的时候,我们需要通过他们解决问题的总时间进行排序。 一共有 N(1<=N<=5,000)条时间被以时(0<=Hours<=99), 分(0<=Minutes<=59),秒(0<=Seconds<=59)的形式记录。 你必须要把他们按时,分,秒排序为 升序,最少的时间最先。 考虑到如下的样例,这三个解出相同题目数量的时间为 11:20:20 11:15:12 14:20:14 正确的排序结果应该是这样的: 11:15:12 11:20:20 14:20:14输入描述:
第 1 行,一个整数 N 第 2~n+1 行,每行 3 个整数,表示时,分,秒
输出描述:
共 n 行,每行 3 个整数,表示排序完后的结果
思路:写个排序函数 直接sort
[cpp] view plain copy print?#include <iostream>#include <stdio.h>
#include <cstring>
#include <set>
#include <map>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1e6+11;
int prime[maxn],cnt;
bool is_prime[maxn];
struct qwe{
int h,m,s;
}q[5015];
int cmp(qwe a,qwe b){
if(a.h!=b.h){
return a.h<b.h;
}
else if(a.m!=b.m){
return a.m<b.m;
}
else return a.s<b.s;
}
int main(){
int n;
while(scanf("%d",&n)!=EOF){
for(int i=0;i<n;i++){
scanf("%d%d%d",&q[i].h,&q[i].m,&q[i].s);
}
sort(q,q+n,cmp);
for(int i=0;i<n;i++){
printf("%d %d %d\n",q[i].h,q[i].m,q[i].s);
}
}
return 0;
}
#include <iostream> #include <stdio.h> #include <cstring> #include <set> #include <map> #include <vector> #include <algorithm> using namespace std; typedef long long ll; const int maxn = 1e6+11; int prime[maxn],cnt; bool is_prime[maxn]; struct qwe{ int h,m,s; }q[5015]; int cmp(qwe a,qwe b){ if(a.h!=b.h){ return a.h<b.h; } else if(a.m!=b.m){ return a.m<b.m; } else return a.s<b.s; } int main(){ int n; while(scanf("%d",&n)!=EOF){ for(int i=0;i<n;i++){ scanf("%d%d%d",&q[i].h,&q[i].m,&q[i].s); } sort(q,q+n,cmp); for(int i=0;i<n;i++){ printf("%d %d %d\n",q[i].h,q[i].m,q[i].s); } } return 0; }
D.训练技巧
题目描述
常州大学组织了新生寒假训练一共N天,每天训练可以获得的训练效果是Ei。但是如果连续训练超过K天,萌新们会受不了而被劝退。 现在负责人想知道,如何安排能保证萌新不会被劝退并且能获得最大的训练效果。输入描述:
第一行:两个用空格隔开的整数:N和K,1≤N≤100000,1≤K≤N 第二行到N+1行:第i+1行有一个整数,表示第N天的训练效果是Ei,(0 <= Ei <= 1,000,000,000)
输出描述:
第一行:单个整数,表示最大的能力之和思路:这应该是10道题里最好得一题 (大佬勿喷)
题目要求我们求最大得训练效果,我们转换下只要求出最小得损失效果,然后用总效果减去即可
怎么求最小损失效果?
我们用dp[i]表示在第i天休息得情况下前i天损失得最小效果,很容易想到dp方程为dp[i]=min(dp[j])+a[i] (j是从i-k-->i-1)
那么这样复杂度就是O(n*k)了
那么我们可以用递增得优先队列维护下[i-k,i-1]内得最小值即可。
[cpp] view plain copy print?#include <bits/stdc++.h>
#include <cstdio>
#include <cmath>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
#define mst(a,b) memset((a),(b),sizeof(a))
typedef long long ll;
const int maxn = 100005;
const ll mod = 1e9+7;
const ll INF = 1e18;
const double eps = 1e-9;
int n,k;
int a[maxn];
ll dp[maxn];
struct qwe{
ll x;
int i;
bool operator < (const qwe& a)const{
return x>a.x;
}
};
int main()
{
while(scanf("%d%d",&n,&k)!=EOF)
{
priority_queue<qwe>q;
qwe tp,num;
mst(dp,0);
ll sum=0;
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
sum+=a[i];
}
for(int i=1;i<=n;i++)
{
if(k+1>=i){
dp[i] = a[i];
num.x=a[i];
}else{
while(q.top().i<(i-k-1)) q.pop();
if(q.top().i>=i-k-1){
dp[i] = q.top().x+a[i];
}
num.x=dp[i];
}
//cout<<dp[i]<<endl;
num.i=i;
q.push(num);
}
ll ans=INF;
for(int i=n-k;i<=n;i++) //求出损失的最小训练效果
{
ans=min(ans,dp[i]);
}
printf("%lld\n",sum-ans);
}
return 0;
}
#include <bits/stdc++.h> #include <cstdio> #include <cmath> #include <queue> #include <cstring> #include <algorithm> using namespace std; #define mst(a,b) memset((a),(b),sizeof(a)) typedef long long ll; const int maxn = 100005; const ll mod = 1e9+7; const ll INF = 1e18; const double eps = 1e-9; int n,k; int a[maxn]; ll dp[maxn]; struct qwe{ ll x; int i; bool operator < (const qwe& a)const{ return x>a.x; } }; int main() { while(scanf("%d%d",&n,&k)!=EOF) { priority_queue<qwe>q; qwe tp,num; mst(dp,0); ll sum=0; for(int i=1;i<=n;i++) { scanf("%lld",&a[i]); sum+=a[i]; } for(int i=1;i<=n;i++) { if(k+1>=i){ dp[i] = a[i]; num.x=a[i]; }else{ while(q.top().i<(i-k-1)) q.pop(); if(q.top().i>=i-k-1){ dp[i] = q.top().x+a[i]; } num.x=dp[i]; } //cout<<dp[i]<<endl; num.i=i; q.push(num); } ll ans=INF; for(int i=n-k;i<=n;i++) //求出损失的最小训练效果 { ans=min(ans,dp[i]); } printf("%lld\n",sum-ans); } return 0; }
E.这是道数学题
题目描述
已知有一个n+1个数的数列,对于给定的A0和An ,当i满足当1<=i<=n-1时有现在小星想知道对于这个数列一段区间的和。
输入描述:
第一行输入四个数 n,A0,An,Q接下来Q行 每行输入两个数l,r0=< n,A0,An<=1e9,Q<=1000000<=l<=r<=n
输出描述:
对于每组查询输出Al到Ar的和思路:
化简一下得:Ai=Ao*C(n-1,i)/C(n,i)+An*C(n-1,i-1)/C(n,i);
再简一下得 Ai = Ao*(n-i)/n+An*i/n ps:为什么?自己再纸上搞搞吧
设组数据看下 例如 n=3
A1 = Ao*2/3+An*1/3
A2 = Ao*1/3+An*2/3
所以 Ao+A1+A2+A3 = Ao*(3/3+2/3+1/3)+An*(1/3+2/3+3/3);可以发现分子和是等差和
那么根据给定得区间以及公式即可求出答案
[cpp] view plain copy print?#include<iostream>
#include<cstdlib>
using namespace std;
typedef long long ll;
int main(){
ll n,Ao,An,q;
//cin >> n >> Ao >> An >> q;
scanf("%lld%lld%lld%lld",&n,&Ao,&An,&q);
for(int i = 1 ; i <=q ;i++)
{
double l,r,a,b;
scanf("%lf%lf",&l,&r);
a = (2*n-l-r)*(r-l+1)*1.0/2.0;
b = (l+r)*(r-l+1)*1.0/2.0;
double s = (a*Ao+b*An)*1.0/n*1.0;
printf("%.0f\n",s);
}
return 0;
}
#include<iostream> #include<cstdlib> using namespace std; typedef long long ll; int main(){ ll n,Ao,An,q; //cin >> n >> Ao >> An >> q; scanf("%lld%lld%lld%lld",&n,&Ao,&An,&q); for(int i = 1 ; i <=q ;i++) { double l,r,a,b; scanf("%lf%lf",&l,&r); a = (2*n-l-r)*(r-l+1)*1.0/2.0; b = (l+r)*(r-l+1)*1.0/2.0; double s = (a*Ao+b*An)*1.0/n*1.0; printf("%.0f\n",s); } return 0; }
G 零下e度
链接:https://www.nowcoder.net/acm/contest/78/G来源:牛客网
题目描述
在家好冷! 又多冷呢? 大概是零下e度! 为什么是零下e度呢? 不知道,因为我编不下去了。 求给定一个数n,求出最接近n!/e的整数输入描述:
一行一个整数n 1<=n<=10^8
输出描述:
一行一个整数,即题目描述中所求,由于这个数字可能很大,我们只需要知道mod 998244353后的结果(出题人负责任地告诉你,这个数字是个质数)思路 :
后面才知道 原来是错排公式 (太弱了 好好补充下数论知识才行
[cpp] view plain copy print?#include <iostream>
using namespace std;
const int mod = 998244353;
typedef long long ll;
int main(){
ll n ;
cin>>n;
ll ans;
if(n==1) ans=1;
if(n==2) ans=2;
ll x=0,y=1;
for(int i=3;i<=n;i++){
ll tem = (x+y)*(i-1)%mod;
x=y;y=tem;
}
if(n>2)
ans = y;
cout<<ans<<endl;
return 0;
}
#include <iostream> using namespace std; const int mod = 998244353; typedef long long ll; int main(){ ll n ; cin>>n; ll ans; if(n==1) ans=1; if(n==2) ans=2; ll x=0,y=1; for(int i=3;i<=n;i++){ ll tem = (x+y)*(i-1)%mod; x=y;y=tem; } if(n>2) ans = y; cout<<ans<<endl; return 0; }
J同分异构体
这题没什么好说,签到题,数据n<=9 直接推出前9种即可[cpp] view plain copy print?#include <iostream>
#include <cstring>
#include <set>
#include <map>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1e6+11;
int prime[maxn],cnt;
bool is_prime[maxn];
int main(){
int n;
while(cin>>n){
if(n<=3) cout<<"1"<<endl;
else if(n==4){
cout<<"2"<<endl;
}
else if(n==5){
cout<<"3"<<endl;
}
else if(n==6){
cout<<"5"<<endl;
}
else if(n==7){
cout<<"9"<<endl;
}
else if(n==8){
cout<<"18"<<endl;
}
else cout<<"35"<<endl;
}
return 0;
}
相关文章推荐
- 常州大学新生寒假训练会试 H 酸碱滴定【精度 】
- 常州大学新生寒假训练会试-G-零下e度(错排公式应用)
- 常州大学新生寒假训练会试 D-训练技巧【动态规划】
- 常州大学新生寒假训练会试-D-训练技巧(DP+单调队列)
- 常州大学新生寒假训练会试 - (E,G,H)
- 常州大学新生寒假训练会试 D 训练技巧【dp + 单调队列优化】
- 常州大学新生寒假训练会试 G 零下e度 【错排公式 + n!/e】
- 【常州大学新生寒假训练会试】D 训练技巧 【单调栈+DP】
- 常州大学新生寒假训练会试
- 常州大学新生寒假训练会试 A-添加逗号
- 常州大学新生寒假训练会试 I-合成反应(bfs)
- 常州大学新生寒假训练会试
- 【常州大学新生寒假训练会试】 合成反应 【BFS or 暴力】
- 常州大学新生寒假训练会试 F-大佬的生日大礼包
- 常州大学新生寒假训练会试 H-酸碱滴定
- 常州大学新生寒假训练会试 题解
- 常州大学新生寒假训练会试 I 合成反应 【 预处理 + 暴力 】
- 常州大学新生寒假训练会试 G-零下e度
- 常州大学寒假练习题解
- [ 牛客网 ] 2018年全国多校算法寒假训练营练习比赛(第三场)— E 进击吧!阶乘