AtCoder Regular Round 152 A - Seat Occupation
思路:
最坏的情况是第一次来的组从第二个位开始坐,此后每次来的组都与前一组空一个位,如果来的是一个人怎样都能坐下,只有一组两个人的情况会坐不下,我们用一个ans维护剩余的连续座位。
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
int main() {
int n, t;
bool flag = 1;
cin >> n >> t;
int a, ans = t;
for (int i = 0; i < n; ++i) {
cin >> a;
if (a == 2 && ans < 2) {
flag = 0;
}
ans -= (a + 1);
}
if (flag)
cout << "Yes\n";
else
cout << "No\n";
return 0;
}
SDNUOJ1263_约瑟夫环递归解法
思路:
很像数学归纳法的递归问题。找出f(n-1,m)和f(n,m)间的关系。
#include <bits/stdc++.h>
using namespace std;
int f(int n) {
return n == 1 ? n : (f(n - 1) + 2) % n + 1;
}
//old=(new+m-1)%n+1
//不是old = (new + m ) % n 的原因是编号是从1开始的
int main() {
int n;
cin >> n;
int ans = f(n);
cout << ans << '\n';
return 0;
}
牛客小白月赛63 E
思路:
先去掉1和n,把剩下n-2个数全排列。然后把1和n和 [ 和 ] 这四个点插进去,跟插板不一样的是,这个插法可以是一个空里插好几个板。我们始终让插进去的最左最右作为 [ , ] ,中间两个是1和n,可以颠倒顺序。所以最终的结果是A(n-2,n-2)*C(n-2+1+3,4)*2。
#include <bits/stdc++.h>
using namespace std;
#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
typedef long long ll;
#define int ll
void work(){
int n;
cin>>n;
if(n<=2){
cout<<n<<'\n';return;
}
ll ans=2;
for(int i=3;i<=n;++i){
ans=ans*(i+2)%998244353;
}
cout<<ans<<'\n';
}
signed main() {
io;
work();
return 0;
}
牛客2022跨年-C
C-翻卡牌_牛客2022跨年场 (nowcoder.com)
思路:
1e9+1%7=0
(x+1e9*x)%7=0。
#include <bits/stdc++.h>
using namespace std;
#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
typedef long long ll;
#define int ll
#define inf 0x3f3f3f3f3f3f3f3f
const int N = 3e5 + 50;
void work() {
string a;cin>>a;
cout<<"0\n";
}
signed main() {
io;
work();
return 0;
}
牛客2022跨年H
H-nana吃蛋糕_牛客2022跨年场 (nowcoder.com)
思路:
n为奇数,易知最大值为所有格之和。
偶数时,至少放弃一个i,j不同奇偶的格子。(其实没太看懂题解但是试了试确实是这样
#include <bits/stdc++.h>
using namespace std;
#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
typedef long long ll;
#define int ll
#define inf 0x3f3f3f3f3f3f3f3f
void work() {
int n;cin>>n;
int sum=0,minn=inf;
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
int a;cin>>a;
sum+=a;
if((i+j)%2!=0){
minn=min(minn,a);
}
}
}
if(n%2!=0){
cout<<sum<<'\n';return;
}else{
cout<<sum-minn<<'\n';
}
}
signed main() {
io;
work();
return 0;
}
牛客小白月赛67E
E-游戏的买_牛客小白月赛67 (nowcoder.com)
思路:
答辩题意。想清楚对于每一天如何确定买还是不买,就速通这题了。
首先要明白今天是知道今天的价钱的,但是不知道以后的价钱。
逆推,最后一天必须买的期望易得是1/2a+1/2b,倒数第二天买不买呢,看期望,如果期望比ab都大那就必须今天买,如果期望比ab都小那今天一定不买,如果期望在ab之间,我们就去等倒数第二天出价,如果出的是小价钱就买,如果是大的就后面买,所以对于之前的天数来说倒数第二天的期望是1/2*min(a,b)+1/2*f[n]。
#include <bits/stdc++.h>
using namespace std;
#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
typedef long long ll;
//#define int ll
#define pb push_back
#define eb emplace_back
#define m_p make_pair
#define mod 998244353
#define mem(a,b) memset(a,b,sizeof a)
#define pii pair<int,int>
#define fi first
#define se second
#define inf 0x3f3f3f3f
const int N = 3e5 + 50;
//__builtin_ctzll(x);后导0的个数
//__builtin_popcount计算二进制中1的个数
int a[N],b[N];
double f[N];
void work() {
int n;cin>>n;
for(int i=1;i<=n;++i){
cin>>a[i];
}for(int i=1;i<=n;++i){
cin>>b[i];
}
f[n]=0.5*a[n]+0.5*b[n];
for(int i=n-1;i>0;--i){
if(f[i+1]>max(a[i],b[i]))f[i]=0.5*a[i]+0.5*b[i];
else if(f[i+1]<min(a[i],b[i]))f[i]=f[i+1];
else f[i]=0.5*f[i+1]+0.5*min(a[i],b[i]);
}
printf("%.15lf\n",f[1]);
}
signed main() {
io;
int t;
cin >> t;
while (t--) {
work();
}
return 0;
}
思路:
数学。
快速枚举n!质因数:对于某一个素数p,在n中,有一个质因数的数有p/n个,有两个的有p/n^2,以此类推,这样的时间是log的。
我写的好像不太好,用了4遍的东西我没写函数,但其实优化不了太多(。
#include <bits/stdc++.h>
using namespace std;
#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
typedef long long ll;
//#define int ll
#define pb push_back
#define eb emplace_back
#define m_p make_pair
#define mod 998244353
#define mem(a,b) memset(a,b,sizeof a)
#define pii pair<int,int>
#define fi first
#define se second
#define inf 0x3f3f3f3f
const int N = 1e7 + 50;
const int M = 1e6 + 50;
//__builtin_ctzll(x);后导0的个数
//__builtin_popcount计算二进制中1的个数
bool is[N];
int tot;
int prime[N];
void euler_sieve() {
tot = 0;
for (int i = 2; i < N; ++i) {
if (!is[i])
prime[tot++] = i;//0为素数
for (int j = 0; j < tot && prime[j]*i < N; ++j) {
is[prime[j]*i] = 1;
if (i % prime[j] == 0)
break;
}
}
}
void work() {
int l1, r1, l2, r2;
cin >> l1 >> r1 >> l2 >> r2;
int n = max(r1, r2);
for (int i = 0; prime[i] <= n; ++i) {
ll t = prime[i];
if (t == 0)
break;
ll a = 0, b = 0, c = 0, d = 0;
while (t <= n) {
a += (l1 - 1) / t;
b += r1 / t;
c += (l2 - 1) / t;
d += r2 / t;
t *= prime[i];
}
if (b - a > d - c) {
cout << "No\n";
return;
}
}
cout << "Yes\n";
}
signed main() {
io;
int t;
cin >> t;
euler_sieve();
while (t--) {
work();
}
return 0;
}
C-小菲爱数数_中国石油大学(北京)第三届“骏码杯”程序设计竞赛(同步赛) (nowcoder.com)
算贡献。
思路:
计算每个因子的贡献。st记录每个因子上次出现的位置。
对于第i位数的一个因子x,他首先有i-st[x]份的贡献是与之前的数组合的,在之后的位数里,如果未出现x,那么now中已经有i-st[x]份属于他的贡献了,每位数都加一个now即每一位都有一个i-st[x]的贡献,直到遇到下一个含x因子的位数重复操作。
#include <bits/stdc++.h>
using namespace std;
#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
typedef long long ll;
#define i64 __int64
//#define int ll
#define pb push_back
#define eb emplace_back
#define m_p make_pair
#define mod 998244353
#define mem(a,b) memset(a,b,sizeof a)
#define pii pair<int,int>
#define fi first
#define se second
#define inf 0x3f3f3f3f
const int N = 1e6 + 50;
//__builtin_ctzll(x);后导0的个数
//__builtin_popcount计算二进制中1的个数
int a[N];
int st[N];
ll now=0,res=0;
void work() {
int n;cin>>n;
vector<int>p;
now=0;res=0;
for(int i=1;i<=n;++i){
cin>>a[i];
int x=a[i];
for(int j=2;j*j<=x;++j){
if(x%j==0){
if(!st[j])p.pb(j);
now+=i-st[j];
while(x%j==0)x/=j;
st[j]=i;
}
}
if(x!=1){
if(!st[x])p.pb(x);
now+=i-st[x];
st[x]=i;
}
res+=now;
}
cout<<res<<'\n';
for(auto x:p){
st[x]=0;
}
}
signed main() {
io;
int t;
cin >> t;
while (t--) {
work();
}
return 0;
}