codeforces 447 A-E div2 补题

DZY Loves Hash 水题

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
bool f[300];
int main()
{
 long long int p,t;
 int i,j,k,m,n;
 cin>>p>>n;
 bool fs=0;
 memset(f,0,sizeof(f));
 for(i=1;i<=n;i++)
   {
   cin>>t;
   t=t%p;
   if(!f[t])f[t]=1;
     else
        {
         fs=1;
         cout<<i;
         break;
        }
   }
 if(!fs)cout<<-1;
 return 0;
}

DZY Loves Strings 水题

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
int main()
{
 ios::sync_with_stdio(false);
 char s[1001];
 int v[26],i,j,k,m,n,maxv=0;
 cin>>s;
 cin>>k;
 for(i=0;i<26;i++)
    {
     cin>>v[i];
     if(v[i]>maxv)maxv=v[i];
    }
 long long int ans=0;
 m=strlen(s);
 for(i=0;i<m;i++)
    ans+=(i+1)*(v[s[i]-‘a‘]);
 for(;i<m+k;i++)
    ans+=(i+1)*maxv;
 cout<<ans;
 return 0;
}

DZY Loves Sequences

枚举修改的位置即可 水

#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn=100005;
typedef long long int LL;
LL num[maxn];
int ac[maxn],dc[maxn];
int main()
{//freopen("t.txt","r",stdin);
 int n;
 scanf("%d",&n);
 for(int i=1;i<=n;i++)
 	scanf("%I64d",&num[i]),ac[i]=dc[i]=1;
 for(int i=1;i<=n;)
 	{
 	 int len=1;
 	 for (int j=i+1;j<=n&&num[j]>num[j-1];j++)len++;
 	 for(int j=i;len>1;len--,j++)
 	 	 ac[j]=len;
 	 i=i+ac[i];
	}
 for(int i=n;i>=1;)
 	{
 	 int len=1;
 	 for (int j=i-1;j>=1&&num[j]<num[j+1];j--)len++;
 	 for(int j=i;len>1;len--,j--)
 	 	 dc[j]=len;
 	 i=i-dc[i];
	}
 dc[0]=ac[0]=dc[n+1]=ac[n+1]=0;
 num[0]=-999999999999LL;
 num[n+1]=9999999999999LL;
 int ans=1;
 for(int i=1;i<=n;i++)
 	{
 	 if(num[i-1]<num[i+1]-1)ans=max(ans,1+dc[i-1]+ac[i+1]);
 	 	else ans=max(ans,max(1+dc[i-1],1+ac[i+1]));
	}
 printf("%d\n",ans);
 return 0;
}

DDZY Loves Modification

给定一个矩阵 进行k次操作 每次取一行或一列 累加他们的和 并且将取中的每一个元素减p

每次找最大行或最大列的贪心方法是错误的。可以找到反例。

那么我们考虑如果p=0 我们找最大行或者最大列 K次即可

如果p不等于0 我们发现一个事实

我们必然取a次行和b次列 a+b=k 且最后答案等于p=0的情况下贪心的ans 减去 a*b*p(尝试自己证明)

于是我们枚举取了多少次行 取最大值就行了。

很有趣的一道贪心题。

#include<bits/stdc++.h>
using namespace std;
typedef long long int LL;
const int N=1005;
LL a[N][N];
LL n,m,k,p;
priority_queue<LL>qr,qc;

int main()
{//freopen("t.txt","r",stdin);
 while(!qr.empty())qr.pop();
 while(!qc.empty())qc.pop();
 scanf("%I64d%I64d%I64d%I64d",&n,&m,&k,&p);
 for(int i=0;i<n;i++)
 	for(int j=0;j<m;j++)
 		scanf("%I64d",&a[i][j]);
 for(int i=0;i<n;i++)
 	{
 	 LL sum=0;
 	 for(int j=0;j<m;j++)
 	 	sum+=a[i][j];
 	 qr.push(sum);
	}
 for(int i=0;i<m;i++)
 	{
 	 LL sum=0;
 	 for(int j=0;j<n;j++)
 	 	sum+=a[j][i];
 	 qc.push(sum);
	}
 LL dr=0,dc=0;
 LL ans=0;
 while(k--)
 	{
 	 if((qr.top()+dr)>(qc.top()+dc))
 	 	{
 	 	 LL num=qr.top();
 	 	 qr.pop();
 	 	 ans+=(num+dr);
 	 	 qr.push(num-p*m);
 	 	 dc-=p;
		}
		else
			{
			 LL num=qc.top();
			 qc.pop();
 	 		 ans+=(num+dc);
 	 	 	 qc.push(num-p*n);
 	 	 	 dr-=p;
			}
	}
 printf("%I64d\n",ans);
 return 0;
}

E. DZY Loves Fibonacci Numbers

首先我们要学习斐波那契数列的两个性质

我们定义原始斐波那契数列即f(1)=f(2)=1 当n>2 f(n)=f(n-1)+f(n-2)

性质一:然后我们定义一般斐波那契数列 即F(1)=a F(2)=b 此时有 F(n)= a*f(n-2)+b*f(n-1)(用归纳法易证得)

性质二:对于一般斐波那契数列的前缀和 我们有如下推导

{fib[n]=fib[n?1]+fib[n?2]fib[n?1]=fib[n?2]+fib[n?3]?fib[n]=fib[n?2]+?+fib[3]+2?fib[2]+fib[1]?∑i=1nfib[i]=fib[n+2]?fib[2]

发现了以上两个性质后 我们可以在常数时间内对斐波那契数列进行分解了!

这意味着我们可以用线段树来储存斐波那契数列了 因为不同的一般斐波那契数列之间显然满足线性可加性。(这样意味着我们可以使用线段树的“懒”功能了)

剩下的看代码吧 有点长 不过很清晰

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#define MAX 300007

using namespace std;

typedef long long LL;

int n,m,a[MAX];
const LL mod = 1e9+9;
LL fib[MAX];

struct Tree
{
    int l,r;
    LL sum,f1,f2;//当前区间要加的一般斐波那契数列前2项(满足线性可加性)
}tree[MAX<<2];

void push_up ( int u )
{
    tree[u].sum = tree[u<<1].sum + tree[u<<1|1].sum;
    tree[u].sum %= mod;
}

void build ( int u , int l , int r )
{
    tree[u].l = l;
    tree[u].r = r;
    tree[u].f1 = tree[u].f2 = 0;
    if ( l == r )
    {
        tree[u].sum = a[l];
        return;
    }
    int mid = l+r>>1;
    build ( u<<1 , l , mid );
    build ( u<<1|1 , mid+1 , r );
    push_up ( u );
}

void init ( )
{
    fib[1] = fib[2] = 1;
    for ( int i = 3 ; i < MAX ; i++ )
    {
        fib[i] = fib[i-1] + fib[i-2];
        fib[i] %= mod;
    }
}

LL get ( LL a , LL b , int n )//一般斐波那契数列的第n项
{
    if ( n == 1 ) return a%mod;
    if ( n == 2 ) return b%mod;
    return (a*fib[n-2]%mod+b*fib[n-1]%mod)%mod;
}

LL sum ( LL a , LL b , int n )//一般斐波那契数列的前缀和
{
    if ( n == 1 ) return a;
    if ( n == 2 ) return (a+b)%mod;
    return ((get ( a , b , n+2 )-b)%mod+mod)%mod;
}

void push_down ( int u )//常数复杂度的拆分
{
    int f1 = tree[u].f1;
    int f2 = tree[u].f2;
    int l = tree[u].l;
    int r = tree[u].r;
    int ll = (l+r)/2-l+1;
    int rr = r-(l+r)/2;
    if ( f1 )
    {
        if ( l != r )
        {
            tree[u<<1].f1 += f1;
            tree[u<<1].f1 %= mod;
            tree[u<<1].f2 += f2;
            tree[u<<1].f2 %= mod;
            tree[u<<1].sum += sum ( f1 , f2 , ll );
            tree[u<<1].sum %= mod;
            int x = f1 , y = f2;
            f2 = get ( x , y , ll+2 );
            f1 = get ( x , y , ll+1 );
            tree[u<<1|1].f2 += f2;
            tree[u<<1|1].f2 %= mod;
            tree[u<<1|1].f1 += f1;
            tree[u<<1|1].f1 %= mod;
            tree[u<<1|1].sum += sum ( f1 , f2 , rr );
            tree[u<<1|1].sum %= mod;
        }
        tree[u].f1 = tree[u].f2 = 0;
    }
}

void update ( int u , int left , int right )
{
    int l = tree[u].l;
    int r = tree[u].r;
    int mid = l+r>>1;
    if ( left <= l && r <= right )
    {
        tree[u].f1 += fib[l-left+1];
        tree[u].f1 %= mod;
        tree[u].f2 += fib[l-left+2];
        tree[u].f2 %= mod;
        int f1 = fib[l-left+1], f2 = fib[l-left+2];
        tree[u].sum += sum ( f1 , f2 , r-l+1 );
        tree[u].sum %= mod;
        return;
    }
    push_down ( u);
    if ( left <= mid && right >= l )
        update ( u<<1 , left , right );
    if ( left <= r && right > mid )
        update ( u<<1|1 , left , right );
    push_up ( u );
}

LL query ( int u , int left , int right )
{
    int l = tree[u].l;
    int r = tree[u].r;
    int mid = l+r>>1;
    if ( left <= l && r <= right )
        return tree[u].sum;
    push_down ( u );
    LL ret = 0;
    if ( left <= mid && right >= l )
    {
        ret += query ( u<<1 , left , right );
        ret %= mod;
    }
    if ( left <= r && right > mid )
    {
        ret += query ( u<<1|1 , left , right );
        ret %= mod;
    }
    return ret;
}

int main ( )
{
    init ( );
    while ( ~scanf ( "%d%d" , &n , &m ) )
    {
        for ( int i = 1; i <= n ; i++ )
            scanf ( "%d" , &a[i] );
        build ( 1 , 1 , n );
        while ( m-- )
        {
            int x,l,r;
            scanf ( "%d%d%d" , &x , &l , &r );
            if ( x == 1 )
                update ( 1 , l , r );
            else
                printf ( "%lld\n" , query ( 1 , l , r ) );
        }
    }
} 

通过这道题 我们对斐波那契数列的认识应该到了一个新的高度了。

 

时间: 2024-11-14 08:27:42

codeforces 447 A-E div2 补题的相关文章

Codeforces Round #634 (Div. 3) 补题

A. Candies and Two Sisters 签到题,直接输出即可 代码 #include<bits/stdc++.h> #define INF 0x3f3f3f3f typedef long long ll; using namespace std; inline void read(int &p) { p=0;int flag=1;char c=getchar(); while(!isdigit(c)) {if(c=='-') flag=-1;c=getchar();} w

codeforces round 422 div2 补题 CF 822 A-F

A I'm bored with life 水题 #include<bits/stdc++.h> using namespace std; typedef long long int LL; const LL N=1,M=1,MOD=1; int main() {//freopen("t.txt","r",stdin); ios::sync_with_stdio(false); LL a,b; scanf("%I64d%I64d",&

codeforces round 418 div2 补题 CF 814 A-E

A An abandoned sentiment from past 水题 #include<bits/stdc++.h> using namespace std; int a[300],b[300],n,k; bool cmp(int a,int b) { return a>b; } int main() {//freopen("t.txt","r",stdin); scanf("%d%d",&n,&k); f

codeforces round 421 div2 补题 CF 820 A-E

A Mister B and Book Reading  O(n)暴力即可 #include<bits/stdc++.h> using namespace std; typedef long long int LL; const LL N=1,M=1,MOD=1; int main() {//freopen("t.txt","r",stdin); int c,v0,v1,a,l; scanf("%d%d%d%d%d",&c,&

CF round416 div2 补题

A. Vladik and Courtesy 水题略过 #include<cstdio> #include<cstdlib> #include<cmath> using namespace std; typedef long long int LL; int main() { LL a,b; scanf("%I64d%I64d",&a,&b); LL num=1; while(true) { if(a<num){printf(&

Codeforces Round #419 (Div. 1) 补题 CF 815 A-E

A-C传送门 D Karen and Cards 技巧性很强的一道二分优化题 题意很简单 给定n个三元组,和三个维度的上限,问存在多少三元组,使得对于给定的n个三元组中的每一个,必有两个维度严格小于. 首先我们根据一个维度(c维)对n个三元组排序,然后枚举答案在这个维度的取值. 此时序列被分成了两个部分,前半部分 满足所有c大于等于i 后半部分满足所有c严格小于i(即已有一个维度小于) 通过累计,我们知道此时前半部a维的最大值ma和b维的最大值mb. 显然可能存在的三元组答案,必然首先满足a维和

BC div2补题以及 复习模除 逆元__BestCoder Round #78 (div.2)

第一题没话说 智商欠费 加老柴辅导终于过了 需要在意的是数据范围为2的63次方-1 三个数相加肯定爆了 四边形的定义 任意边小于其余三边之和 换句话说就是 最长边小于其余三边之和 这样的话问题转化为 最长边依次减其余三边的结果是否小于等于0 还有一点是题目出现0边 即最小边不为0 想得太多反而把0也算为合法.... 问题只需要 sort一下 判断a[0]==0||a[3]-a[2]-a[1]-a[0]<=0 输出NO 第二题 好多种姿势 题目链接http://bestcoder.hdu.edu.

Codeforces Round #590 (Div. 3)补题

要想上2000分,先刷几百道2000+的题再说 ---某神 题目 E F 赛时是否尝试 × × tag math bitmask 难度 2000 2400 状态 ? √ 解 E 待定 F 传送门 第一次接触状态压缩dp的题.这道题转换问题的思路非常巧妙. 原问题: 已知: 一个字符串,可进行不超过一次操作 操作限定: 选择某个子串,使其在原串中翻转 目的:使原串的特征值最大 串的特征值:串任意没有重复字符的子串,其包含字符的种类数 问题的转换: 首先选定一个子串a,之后再找到另一个子串b,使得a

Codeforces Round #617 (Div. 3) 补题记录

1296A - Array with Odd Sum 题意:可以改变数组中的一个数的值成另外一个数组中的数,问能不能使数组的和是个奇数 思路:签到,如果本来数组的和就是个奇数,那就OK 如果不是,就需要把数组中其中一个奇(偶)数改成偶(奇)数,相当于加一减一 所以测一下这个数组如果有个奇数并且还有个偶数就行 #include <cstdio> #include <iostream> #include <map> #include <set> #include