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 ,显然 0≤qi≤m−1 。
其中若有 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[i−1][j] 或 dp[i−1][(j−a[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个点构成的且曼哈顿距离不超过 25∗108 的哈密尔顿路径
思路:
据说莫队算法可以搞。
但这题可以简化下:
要保证相邻点间的曼哈顿距离之和小于
25∗108
,就是从左到右将原来的
106∗106
的坐标系转化成1000个
103∗106
的区域,相邻区域的路径走向一上一下即可。
代码:
/*
* @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;
}