Dashboard - Codeforces Round 919 (Div. 2) - Codeforces
B写崩了
丑陋的代码
删掉一个数一定比把这个数留着乘-1更好
前缀和预处理,从后往前枚举每种情况
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;
typedef long long LL;
#define int long long
typedef pair<int,int> PII;
const int N=1000010;
int a[N];
bool st[N];
int sum[N],sum2[N];
void solve(){
int n,k,x;
cin>>n>>k>>x;
sum[0]=0;
int res=0;
for(int i=1;i<=n;i++){
cin>>a[i];
res+=a[i];
}
sort(a+1,a+1+n);
for(int i=1;i<=n;i++){
sum[i]=sum[i-1]+a[i];
}
int tt=res-2*(sum[n]-sum[n-x]);
for(int i=0;i<=k;i++){
int ans2=sum[max((int)0,n-i)]-2*(sum[max((int)0,n-i)]-sum[max((int)0,(n-i-x))]);
tt=max(tt,ans2);
}
cout<<tt<<endl;
}
signed main(){
int t=1;
cin>>t;
while(t--){
solve();
}
}
C
分解一下因子,我们假设现在是因子x,每个块的长度都是x,我们需要关心的是是否存在一个m使得 (1,1+x,1+2x…… )(2,2+x,2+2x……)这类块中所有数模m后的余数相等
思考:如何凑出这样一个m?
我们可以把每个块中的差(相邻两数,不是也没关系但一定要保证数与数之间的联通性,因为这样我们可以保证这个正确性),求gcd,因为m对于所有块是固定不会变的,这时gcd不是1,就存在m
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;
typedef long long LL;
#define int long long
typedef pair<int,int> PII;
const int N=1000010;
int a[N];
bool st[N];
int sum[N],sum2[N];
void solve(){
int n,k,x;
cin>>n;
std::vector<int>v;
map<int,int>mp;
int gg=0;
for(int i=1;i<=n;i++){
cin>>a[i];
gg=__gcd(gg,a[i]);
mp[a[i]]++;
}
for(int i=1;i<=n/i;i++){
if(n%i)continue;
v.push_back(i);
if(i!=n/i){
v.push_back(n/i);
}
}
int ans=0;
for(auto c:v){
int f=1;
int g=0;
for(int i=1;i<=c;i++){
//mp<int,int>mp;
for(int j=i+c;j<=n;j+=c){
if(a[j]==a[i])continue;
g=__gcd(abs(a[j]-a[i]),g);
}
if(g==1){
f=0;
break;
}
}
if(f ){
ans++;
}
}
cout<<ans<<endl;
}
signed main(){
int t=1;
cin>>t;
while(t--){
solve();
}
}
D
我们用add数组记录直接添加的节点和翻倍时的刚好的倍数节点
dp数组存储现长度
当查询的位置很大时,我们可以在dp数组(从后到前循环,因为翻倍从从前到后)中找到它翻倍之前的长度
情况1:当好是节点上的点,或是通过操作1得到的点,这时直接退出即可,因为这些点我们已经记录下来了
情况2:其他点,说明k是一次翻倍的点,且不是节点,直接对dp数组取模,可以得到k在翻倍前的位置,这时就继续判断如果是情况1则跳出,如果是情况2就继续即可
这这个过程不会太长因为题目限制了1e18的长度,而且是log级别的
#include <iostream>
#include <cstring>
#include <algorithm>
#include<vector>
using namespace std;
#define int long long
void solve(){
int n,q;
cin>>n>>q;
int dp[n+1]={};
int add[n+1]={};
vector<int>pos;
for(int i=1,ok=true;i<=n;i++){
int op,x;
cin>>op>>x;
if(op==1){
dp[i]=dp[i-1]+1;
add[i]=x;
}else{
if(x+1>2e18/dp[i-1]){
dp[i]=2e18;
}else{
dp[i]=dp[i-1]*(x+1);
}
add[i]=add[i-1];
if(ok) pos.push_back(i);
}
if(dp[i]==2e18) ok=false;
}
while(q--){
int k;
cin>>k;
for(int i=pos.size()-1;i>=0;i--){
int idx=pos[i];
if(dp[idx] >k && dp[idx-1]<k){
if(k%dp[idx-1]==0){
k=dp[idx-1];
break;
}
k%=dp[idx-1];
}
}
cout<<add[lower_bound(dp+1,dp+1+n,k)-dp]<<" ";
}
cout<<endl;
}
signed main(){
int t;
cin>>t;
while(t--){
solve();
}
}