Codeforces Round #319 (Div. 2)(A,B,C,E)

Codeforces Round #319 (Div. 2)

A.Multiplication Table

题意:

求m在n*n的加法表中出现了几次

思路:

枚举1到n,累计能整除m的情况。

代码:
/*
* @author FreeWifi_novicer
* language : C++/C
*/
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<string>
#include<map>
#include<set>
#include<vector>
#include<queue>

using namespace std;

#define clr( x , y ) memset(x,y,sizeof(x))
#define cls( x ) memset(x,0,sizeof(x))
#define mp make_pair
#define pb push_back
typedef long long lint;
typedef long long ll;
typedef long long LL;

int main(){
//  freopen("input.txt","r",stdin);
    lint n , x;
    while( cin >> n >> x ){
        lint cnt = 0 ;
        for( lint i = 1 ; i <= n ; i++ ){
            if( x >= i && x % i == 0 && x / i <= n ) cnt++ ;
        }
        cout << cnt  << endl ;
    }
    return 0;
}

B. Modulo Sum

题意:

输入n个数以及m,问能否从n中选一些数,这些数的和能被m整除。

思路:

分两种情况:

n >= m

n >= m 时,必定YES,证明如下:
考虑n个数的前i项和,每一个前i项和 sumi%m=qi ,显然 0qim1
其中若有 qi=0 ,则YES;若所有 qi 均不为 0,则必存在两个或以上的 qi 相等 (因为共有n个前i项和), 即存在两个不相等的 sumi 模除 m 的值相等,绝对差值即为 m 的倍数,故也是YES。

n < m

n < m 时 , 我们用 dp[i][j] 表示前i项是否存在组合除以m得到余数j,那么答案就是 dp[n][0]
显然, dp[i][a[i]]=true ;此外状态 dp[i][j] 可以由 dp[i1][j] dp[i1][(ja[i]+m)%m] 转移而得,只要这两种状态其中任一项为真,则 dp[i][j] 也为真 。

貌似数据不算特别强,排序后多写几个特判其实也可以水过去(不推荐

代码:
/*
 * @author FreeWifi_novicer
 * language : C++/C
 */
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<string>
#include<map>
#include<set>
#include<vector>
#include<queue>

using namespace std;

#define clr( x , y ) memset(x,y,sizeof(x))
#define cls( x ) memset(x,0,sizeof(x))
#define mp make_pair
#define pb push_back
typedef long long lint;
typedef long long ll;
typedef long long LL;

const int maxn = 1e6 + 5 ;
int a[maxn] ;
bool dp[3005][3005] ;
int main(){
    //  freopen("input.txt","r",stdin);
    int n , mod ;
    while( cin >> n >> mod ){
        bool ok = false ;
        if( n >= mod ) ok = true ;
        for( int i = 1 ; i <= n ; i++ ){
            scanf( "%d" , a+i ) ;
            a[i] %= mod ;
            if( a[i] % mod == 0 ) ok = true ;
        }
        if( ok ){
            puts( "YES" ) ;
            continue ;
        }
        clr( dp , false ) ;
        for (int i = 1; i <= n ;i ++)
            dp[i][a[i]] = 1;

        for( int i = 2 ; i <= n ; i++ ){
            for( int j = 0 ; j < mod  ; j++ ){
                dp[i][j] |= dp[i-1][j] ;
                int tmp = ( j - a[i] + mod ) % mod ;
                dp[i][j] |= dp[i-1][tmp] ;
            }
        }
        if( dp[n][0] ) ok = true ;
        if(ok)
            puts( "YES" ) ;
        else
            puts( "NO" ) ;
    }
    return 0;
}

C.Vasya and Petya’s Game

题意:

输入一个未知数n,可以询问n是否能被某个数整除,现在告诉你n,求出最少询问哪些数后,可以必定求出n。

思路:

看似比较难。。其实比B简单很多。
要区分 pk pk+1 ,唯一的办法就是询问能否被 pk 整除与能否被 pk+1 整除。。
所以输出所有不超过n的 pk 即可 。

代码:
/*
* @author FreeWifi_novicer
* language : C++/C
*/
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<string>
#include<map>
#include<set>
#include<vector>
#include<queue>

using namespace std;

#define clr( x , y ) memset(x,y,sizeof(x))
#define cls( x ) memset(x,0,sizeof(x))
#define mp make_pair
#define pb push_back
typedef long long lint;
typedef long long ll;
typedef long long LL;

const int maxn = 1e3 + 5 ;
bool noprime[maxn] ;
vector<int>p ;
int sieve( int n ){
    cls( noprime ) ;
    p.clear() ;
    for( int i = 2 ; i * i <= n ; i++ )
        if( !noprime[i] )
            for( int j = i * i ; j <= n ; j += i )
                noprime[j] = true ;
    for( int i = 2 ; i <= n ; i++ )
        if( !noprime[i] )
            p.pb(i) ;
    return p.size() ;
}

vector<int>ans ;
int main(){
//  freopen("input.txt","r",stdin);
    int n ;
    while( cin >> n ){
        if( n == 1 ){
            cout << 0 << endl ;
            continue ;
        }
        ans.clear() ;
        int num = sieve( n ) ;
        for( int i = 0 ; i < num ; i++ ){
            int k = p[i] ;
            while( k <= n ){
                ans.pb( k ) ;
                k *= p[i] ;
            }
        }
        cout << ans.size() << endl ;
        for( int i = 0 ; i < int( ans.size() ) ; i++ ){
            cout << ans[i] << ' ' ;
        }
        cout << endl ;
    }
    return 0;
}

D. Invariance of Tree(还没做..

E. Points on Plane

题意:

求n个点构成的且曼哈顿距离不超过 25108 的哈密尔顿路径

思路:

据说莫队算法可以搞。
但这题可以简化下:
要保证相邻点间的曼哈顿距离之和小于 25108 ,就是从左到右将原来的 106106 的坐标系转化成1000个 103106 的区域,相邻区域的路径走向一上一下即可。

代码:
/*
* @author FreeWifi_novicer
* language : C++/C
*/
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<string>
#include<map>
#include<set>
#include<vector>
#include<queue>

using namespace std;

#define clr( x , y ) memset(x,y,sizeof(x))
#define cls( x ) memset(x,0,sizeof(x))
#define mp make_pair
#define pb push_back
typedef long long lint;
typedef long long ll;
typedef long long LL;

const int maxn = 1e6 + 500 ;
const int len = 1e3 ;
struct Point{
    int x , y , id ;
}p[maxn] ;
bool cmp( Point a , Point b ){
    if( a.x / len != b.x / len ) return a.x / len < b.x / len ;
    if( ( a.x / len ) & 1 ) return a.y < b.y ;
    return a.y > b.y ;
}
int main(){
//  freopen("input.txt","r",stdin);
    int n ; cin >> n ;
    for( int i = 1 ; i <= n ; i++ ){
        scanf( "%d%d" , &p[i].x ,&p[i].y ) ;
        p[i].id = i ;
    }
    sort( p + 1 , p + 1 + n , cmp ) ;
    for( int i = 1 ; i <= n ; i++ ) cout << p[i].id << ' ' ;
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值