B. Bounty Hunter II
题目链接:https://nanti.jisuanke.com/t/18486
题意:给定几个点及其边,问派几个人可以遍历这些点,前提是每个点只能一个人走。
更为清晰的说法是题解中的:
Given a DAG with N nodes find the minimum number of vertex-disjoint
paths to cover each vertex.
思路:没想到竟然是二分图匹配。。。
Code:
#include <bits/stdc++.h>
using namespace std ;
const int AX = 1e3+6;
int G[AX][AX];
int used[AX];
int link[AX];
int n ;
bool dfs( int u ){
for( int i = 0 ; i < n ; i++ ){
if( G[u][i] && !used[i] ){
used[i] = 1;
if( link[i] == -1 || dfs( link[i] ) ){
link[i] = u ;
return true;
}
}
}
return false;
}
int xyl(){
int res = 0 ;
memset( link , -1 , sizeof(link) );
int u ;
for( u = 0 ; u < n ; u++ ){
memset( used , 0 , sizeof(used) );
if( dfs(u) ) res ++;
}
return res;
}
int main(){
scanf("%d",&n);
int x , y ;
for( int i = 0 ; i < n ; i++ ){
scanf("%d",&x);
for( int j = 0 ; j < x ; j++ ){
scanf("%d",&y);
G[i][y] = 1 ;
}
}
int ans = xyl();
/*for( int i = 0 ; i < n ; i++ ){
cout << "link[ " << i << " ] " << link[i] << endl;
}*/
printf("%d\n",n-ans);
return 0 ;
}
E. Change of Scenery
题目链接:https://nanti.jisuanke.com/t/28394
题意:给出一个最短路及其各点和边,问有没有其他最短路。(题意开始错误理解成必须经过给定的节点。。然后以为dp。。)
思路:给的最短路没有用,直接求是否有两条以上最短路即可。用的是队列优化的dijstra算法,加一个每个点的路径记录次数的数组。
Code:
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
const int AX = 1e4+666;
typedef pair<int,int> P ;
std::vector<P> G[AX];
int dis[AX];
int vis[AX];
int num_road[AX];
void dijstra(){
priority_queue<P,vector<P>,greater<P> >q ;
q.push(P(0,1));
dis[1] = 0 ;
num_road[1] = 1 ;
while( !q.empty() ){
int u = q.top().second;
int val = q.top().first;
q.pop();
if( vis[u] ) continue;
vis[u] = 1 ;
if( val > dis[u] ) continue;
for( int i = 0 ; i < (int)G[u].size() ; i++ ){
int v = G[u][i].first;
int w = G[u][i].second;
if( dis[v] > val + w ){
dis[v] = val + w ;
num_road[v] = num_road[u] ;
q.push( P( dis[v] , v ) );
}else if( dis[v] == val + w ){
num_road[v] = 2 ;
}
}
}
}
int main(){
int n , m , k ;
scanf("%d%d%d",&n,&m,&k);
int x , y , z ;
memset( dis , INF, sizeof(dis) );
memset( num_road , 0 , sizeof(num_road ));
memset( vis , 0 , sizeof(vis) ) ;
for( int i = 0 ; i < k ; i++ ) scanf("%d",&x);
for( int i = 0 ; i < m ; i++ ){
scanf("%d%d%d",&x,&y,&z);
G[x].push_back(P(y,z));
G[y].push_back(P(x,z));
}
dijstra();
if( num_road[n] > 1 ) printf("yes\n");
else printf("no\n");
return 0;
}
F. Divisions
题目链接:https://nanti.jisuanke.com/t/28395
题意:给出一个数(<1e16)输出因子个数
思路:因子个数就是对合数分解质因数,每个质因数的次方数加1,相乘。
数据过大用pollard rho算法和米勒拉宾素数测试。
Code:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <cstdlib>
#define LL long long
using namespace std;
const int S = 10;
LL mult( LL a , LL b , LL c ) {
a %= c ;
b %= c ;
LL ret = 0;
while( b ){
if( b & 1 ){
ret = ( ret + a ) % c ;
}
b >>= 1 ;
a <<= 1 ;
if( a >= c ) a %= c ;
}
return ret;
}
LL quick( LL a , LL b , LL m ){
LL res = 1;
while( b ){
if( b & 1 ){
res = mult( res , a , m );
}
b >>= 1 ;
a = mult( a , a , m ) % m ;
}
return res ;
}
bool check( LL a, LL n , LL x , LL t ){
LL ret = quick( a , x , n );
LL last = ret ;
for( int i = 1 ; i <= t ; i++ ){
ret = mult( ret , ret , n ) ;
if( ret == 1 && last != 1 && last != n - 1 ) return true;
last = ret ;
}
if( ret != 1 ) return true ;
return false;
}
bool Miller_Rabin( LL n ){
if( n < 2 ) return false;
if( n == 2 ) return true;
if( !( n & 1 ) ) return false;
LL x = n - 1;
LL t = 0 ;
while( !(x & 1) ){
x >>= 1;
t ++ ;
}
srand(time(NULL));
for( int i = 0 ; i < S ; i++ ){
LL a = rand() % ( n - 1 ) + 1;
if( check( a , n , x , t ) ) return false;
}
return true;
}
LL factor[100];
int tot ;
LL gcd( LL a , LL b){
if( !a ) return 1;
if( a < 0 ) return gcd( -a , b );
while( b ){
LL t = a % b ;
a = b ;
b = t ;
}
return a;
}
LL pollard_rho( LL x , LL c ){
LL i = 1 , k = 2 ;
srand(time(NULL));
LL x0 = rand() % (x-1) + 1 ;
LL y = x0;
while(1){
i ++;
x0 = ( mult( x0 , x0 , x ) + c ) % x;
LL d = gcd( y - x0 , x );
if( d != 1 && d != x ) return d;
if( y == x0 ) return x;
if( i == k ){
y = x0 ;
k += k;
}
}
}
void findfac( LL n , int k ){
if( n == 1 ) return;
if( Miller_Rabin(n) ){
factor[tot++] = n ;
return ;
}
LL p = n ;
int c = k ;
while( p >= n ) p = pollard_rho( p , c-- );
findfac( p , k );
findfac( n / p , k );
}
int main(){
LL n ;
scanf("%lld",&n);
if( Miller_Rabin(n) ){
printf("2\n");
}else{
tot = 0 ;
findfac( n , 107 ) ;
LL res = 1LL;
for( int i = 0 ; i < tot ; i++ ){
int cnt = 0 ;
while( n > 0 && ( n % factor[i] == 0 ) ){
cnt ++ ;
n /= factor[i];
}
if( cnt ) res *= ( cnt + 1 );
}
printf("%lld\n",res);
}
return 0 ;
}
G. Extreme Sort
签到题
Code:
#include <bits/stdc++.h>
using namespace std;
const int AX = 1e3+66;
int a[AX];
int main(){
int n;
cin >> n ;
for( int i = 0 ; i < n ; i ++ ){
cin >> a[i];
}
for( int i = 0 ; i < n ; i++ ){
for( int j = i + 1 ; j < n ; j++ ){
if( a[j] < a[i] ){
cout << "no" << endl;
return 0 ;
}
}
}
cout << "yes" << endl;
return 0 ;
}
H. Legacy Code
题目链接:https://nanti.jisuanke.com/t/28397
题意:妥妥的英文理解题,理解了秒过。给出2*n行,(n组),所有组第一行构成了程序的所有方法,带有PROGRAM字样的是可执行的,第二行是你执行的名字,(只有带PROGRAM才能执行,进而调用别的方法)
思路:bfs一次即可。
Code:
#include <bits/stdc++.h>
using namespace std;
map<string,int>mp;
const int AX = 1e3+66;
int vis[AX];
std::vector<int> G[AX];
int main(){
int n ;
cin >> n ;
int k ;
int tot = 1 ;
queue<int>q;
for( int i = 0 ; i < n ; i++ ){
string name ;
cin >> name >> k;
if( !mp[name] ) mp[name] = tot ++;
int id = mp[name];
if( name.find("::PROGRAM") == name.size() - 9 && name.size() != 8 ){
q.push(id);
vis[id] = 1;
}
while( k ){
cin >> name ;
if( !mp[name] ) mp[name] = tot ++;
G[mp[name]].push_back(id);
k --;
}
}
while( !q.empty() ){
int tmp = q.front();
q.pop();
for( int i = 0 ; i < G[tmp].size() ; i++ ){
if( !vis[G[tmp][i]] ){
q.push(G[tmp][i]);
vis[G[tmp][i]] = 1 ;
}
}
}
int res = 0 ;
for( int i = 1 ; i < tot ; i++ ){
if( !vis[i] ){
res ++ ;
}
}
cout << res << endl;
return 0 ;
}
I. Milling machines
题目链接:https://nanti.jisuanke.com/t/28398
也是签到题。
Code:
#include <bits/stdc++.h>
using namespace std;
const int AX = 1e4+666;
int a[AX][105];
int b[AX];
int main(){
int w , s ;
int x , y ;
cin >> w >> s ;
cin >> x >> y ;
for( int i = 0 ; i < w ; i++ ){
for( int j = 0 ; j < x ; j++ ){
cin >> a[i][j];
}
}
int tmp;
for( int i = 0 ; i < s ; i++ ){
for( int j = 0 ; j < x ; j++ ){
cin >> tmp ;
b[j] = max( b[j] , tmp );
}
}
for( int i = 0 ; i < w ; i ++ ){
for( int j = 0 ; j < x ; j++ ){
cout << ( a[i][j] > ( y - b[j] ) ? (y-b[j]) : a[i][j] ) ;
if( j != x - 1 ) cout << ' ';
}
if( i != w - 1 ) cout << endl;
}
return 0 ;
}
K. Upside down primes
题目链接:https://nanti.jisuanke.com/t/28400
题意:如果输入的数是素数且左右反转一下仍为素数则输出yes,否则no
思路:注意含有3 4 7 的都不行,而且6反过来是9,9反过来是6就行了。
可以用朴素的判断素数,也可以用米勒拉宾素数测试判断更快。
Code:
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int AX = 1e2+6;
int main(){
string s ;
cin >> s ;
LL n = 0LL ;
LL nn = 0LL ;
int len = s.size();
if( s.size() == 1 ){
if( s[0] == '2' ){
cout << "yes" << endl;
return 0 ;
}
if( s[0] == '1' ){
cout <<"no" << endl;
return 0 ;
}
}
for(int i = 0 ; i < len ; i++ ){
nn = nn * 10 + ( s[i] - '0' ) ;
}
LL lim = sqrt(nn) ;
for( LL i = 2 ; i <= lim ; i++ ){
if( nn % i == 0 ){
cout << "no" << endl;
return 0 ;
}
}
for(int i = 0 ; i < len ; i++){
if( s[i] == '3' || s[i] == '4' || s[i] == '7' ){
cout << "no" << endl;
return 0 ;
}
}
for( int i = len - 1; i >= 0 ; i-- ){
if( s[i] == '9' ) n = n * 10 + 6 ;
else if( s[i] == '6' ) n = n * 10 + 9 ;
else n = n * 10 + ( s[i] - '0' ) ;
}
/*if( Miller_Rabin(nn) && Miller_Rabin(n) ){
cout << "yes" << endl;
}else cout << "no" << endl;*/
lim = sqrt(n) ;
for( LL i = 2 ; i <= lim ; i++ ){
if( n % i == 0 ){
cout << "no" << endl;
return 0 ;
}
}
cout << "yes" << endl;
return 0 ;
}