Problem A: Miss SOJ
题意:求满足n!%s^k最大的k
对s进行素因子分解,然后对每个素因子用n去除即可求出n!中此素因子的个数,取最小值更新答案即可。
#include <cstring>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <climits>
using namespace std;
const int MaxN = 1000005;
int cnt[1000005];
bool isPrime[MaxN];
long long tot, p[MaxN];
void getPrime()
{
fill(isPrime, isPrime + MaxN, true);
isPrime[0] = isPrime[1] = 0;
tot = 0;
for (int i = 2; i < MaxN; i++)
{
if (isPrime[i]) p[tot++] = i;
for (int j = 0; j < tot; j++)
{
if (i * p[j] >= MaxN) break;
isPrime[i * p[j]] = false;
if (i % p[j] == 0) break;
}
}
}
int main()
{
long long n,s,now,ans,tmp=0;
int t,maxx;
getPrime();
scanf("%d",&t);
while(t--)
{
scanf("%lld%lld",&n,&s);
maxx=-1;
for(int i=0; p[i]*p[i]<=s; ++i)
{
maxx=max(maxx,i);
while(s%p[i]==0)
{
s/=p[i];
++cnt[p[i]];
}
}
now=n;
ans=LONG_LONG_MAX;
if(s!=1)
{
tmp=0;
while(now)
{
tmp+=now/s;
now/=s;
}
ans=min(ans,tmp);
}
for(int i=0; i<=maxx; ++i)
{
if(cnt[p[i]])
{
now=n;
tmp=0LL;
while(now)
{
tmp+=now/p[i];
now/=p[i];
}
ans=min(ans,tmp/cnt[p[i]]);
}
}
printf("%lld\n",ans);
memset(cnt,0,sizeof(cnt));
}
return 0;
}
Problem B: Longest Common Subsequence
题意:求LCS
LCS是O(N^2)的很容易得到TLE,可以考虑用map离散转为LIS,LIS的O(NlogN)的复杂度足以通过此题LIS nlogn 戳我
#include <cstring>
#include <iostream>
#include <cstdlib>
#include <cctype>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <queue>
#define MAXN 100005
using namespace std;
int b,a[MAXN],anss[MAXN];
map<int,int>ma;
template <class T>
int bsearch(T c[],int n,T a)
{
int l=1, r=n;
while(l<=r)
{
int mid = (l+r)/2;
if( a > c[mid] && a <= c[mid+1] )
return mid+1;
else if( a < c[mid] )
r = mid-1;
else l = mid+1;
}
}
template<class T>
int LIS(T a[], int n)
{
int i, j, size = 1;
T *c=new T[n+1];
int *dp=new int[n+1];
c[1] = a[1]; dp[1] = 1;
for(i=2;i<=n;++i)
{
if( a[i] <= c[1] ) j = 1;
else if( a[i] >c[size] )
j=++size;
else
j = bsearch(c, size, a[i]);
c[j] = a[i]; dp[i] = j;
}
return size;
}
int main()
{
int n,cnt;
while(cin>>n){
ma.clear();
cnt=1;
memset(a,0,sizeof(a));
memset(anss,0,sizeof(anss));
for(int i=1;i<=n;++i){
scanf("%d",a+i);
ma[a[i]]=i;
}
for(int i=1;i<=n;++i){
scanf("%d",&b);
if(ma.count(b)!=0)anss[cnt++]=ma[b];
}
if(cnt==1){cout<<"0"<<endl;continue;}
cout<<LIS(anss,cnt)<<endl;
}
return 0;
}
Problem D: Farmer John
裸的MST
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <algorithm>
#include <numeric>
#define MAXN 2*100005
using namespace std;
int u[MAXN], v[MAXN], w[MAXN];
int p[MAXN], r[MAXN];
int n, m;
bool cmp(int i, int j) {
return w[i] < w[j];
}
int find_(int x) {
return p[x] == x ? x : p[x] = find_(p[x]);
}
long long Kruskal() {
long long ans = 0;
for(int i = 0; i < n + 1; i++) {
p[i] = i;
}
for(int i = 0; i < m + n; i++) {
r[i] = i;
}
sort(r, r + m + n, cmp);
for(int i = 0; i < m + n; i++) {
int e = r[i]; int x = find_(u[e]); int y = find_(v[e]);
if(x != y) {
ans += w[e]; p[x] = y;
}
}
return ans;
}
int main() {
while(scanf("%d%d", &n, &m) != EOF) {
for(int i = 0; i < n; i++) {
u[i] = 0;
v[i] = i + 1;
scanf("%d", &w[i]);
}
for (int i = n; i < m + n; ++ i) {
scanf("%d%d%d", &u[i], &v[i], &w[i]);
}
printf("%lld\n", Kruskal());
}
return 0;
}
Problem E: Ticket and balance
三进制法,1表示放左,2表示放右,0表示不放,判机票价格可以通过取模比较
#include <cstring>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <climits>
#include <utility>
using namespace std;
int a,b,n,v[15];
long long ans,maxx;
vector <int> w;
vector <long long> vis;
int go(int a,vector <int>& w)
{
w.clear();
while(a)
{
w.push_back(a%3);
a/=3;
}
return w.size();
}
long long pow_mod(long long a,long long b)
{
long long ans=1;
a%=7;
while(b)
{
if(b&1LL)ans=(ans*a)%7;
a=(a*a)%7;
b>>=1;
}
return ans;
}
int my_pow(int n)
{
int ans=1;
for(int i=0;i<n;++i)ans*=3;
return ans;
}
int main()
{
while(scanf("%d%d%d",&a,&b,&n)==3)
{
vis.clear();
for(int i=0;i<n;++i)scanf("%d",v+i);
int cnt=my_pow(n);
maxx=v[0];
for(int i=0;i<cnt;++i)
{
int len=go(i,w);
ans=0;
for(int j=0;j<len;++j)
{
if(w[j]==1)ans+=v[j];
else if(w[j]==2) ans-=v[j];
}
ans=ans<0?-ans:ans;
maxx=max(ans,maxx);
vis.push_back(ans);
}
sort(vis.begin(),vis.end());//此处为去重过程
vis.erase(unique(vis.begin(),vis.end()),vis.end());
long long tic=pow_mod((long long)a,(long long)b);
if(tic==0||tic==6)tic=800;
else tic=1000;
printf("%lld %d %lld\n",tic,vis.size()-1,maxx);
}
return 0;
}
Problem F: Sudoku
很裸的DLX,详见大白书P406
#include <cstring>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <strstream>
#include <map>
#include <set>
#include <queue>
#include <climits>
#include <utility>
#include <stdlib.h>
using namespace std;
int n;
struct DLX
{
const static int maxn=20010;
int n,sz;
int S[maxn];
int row[maxn],col[maxn];
int L[maxn],R[maxn],U[maxn],D[maxn];
int ansd,ans[maxn];
void init(int n)
{
this->n=n;
for(int i=0;i<=n;++i)
{
U[i]=i;
D[i]=i;
L[i]=i-1;
R[i]=i+1;
}
R[n]=0;
L[0]=n;
sz=n+1;
memset(S,0,sizeof(S));
}
void addRow(int r,vector <int> columns)
{
int first=sz;
for(int i=0;i<columns.size();++i)
{
int c=columns[i];
L[sz]=sz-1;R[sz]=sz+1;D[sz]=c;U[sz]=U[c];
D[U[c]]=sz;U[c]=sz;
row[sz]=r;col[sz]=c;
S[c]++;sz++;
}
R[sz-1]=first;L[first]=sz-1;
}
#define FOR(i,A,s) for(int i=A[s];i!=s;i=A[i])
void remove (int c)
{
L[R[c]]=L[c];
R[L[c]]=R[c];
FOR(i,D,c)
FOR(j,R,i){U[D[j]]=U[j];D[U[j]]=D[j];--S[col[j]];}
}
void restore(int c)
{
FOR(i,U,c)
FOR(j,L,i){++S[col[j]];U[D[j]]=j;D[U[j]]=j;}
L[R[c]]=c;
R[L[c]]=c;
}
bool dfs(int d)
{
if(R[0]==0){ansd=d;return true;}
int c=R[0];
FOR(i,R,0)if(S[i]<S[c])c=i;
remove(c);
FOR(i,D,c){
ans[d]=row[i];
FOR(j,R,i)remove(col[j]);
if(dfs(d+1))return true;
FOR(j,L,i)restore(col[j]);
}
restore(c);
return false;
}
bool solve(vector <int>& v)
{
v.clear();
if(!dfs(0))return false;
for(int i=0;i<ansd;++i)v.push_back(ans[i]);
return true;
}
};
DLX slover;
const int SLOT=0;
const int ROW=1;
const int COL=2;
const int SUB=3;
int encode(int a,int b,int c){return a*n*n+b*n+c+1;}
void decode(int code,int& a,int& b,int& c)
{
code--;
c=code%n;code/=n;
b=code%n;code/=n;
a=code;
}
int puzzle[20][20];
int main()
{
//freopen("in.txt","r",stdin);
while(scanf("%d",&n)==1)
{
for(int i=0;i<n;++i){
for(int j=0;j<n;++j){
scanf("%d",&puzzle[i][j]);
}
}
const int M=(int)sqrt(n);
slover.init(n*n*4);
for(int r=0;r<n;++r)
{
for(int c=0;c<n;++c)
{
for(int v=0;v<n;++v)
{
if(puzzle[r][c]==0||puzzle[r][c]==v+1)
{
vector <int> coulumns;
coulumns.push_back(encode(SLOT,r,c));
coulumns.push_back(encode(ROW,r,v));
coulumns.push_back(encode(COL,c,v));
coulumns.push_back(encode(SUB,r/M*M+c/M,v));
slover.addRow(encode(r,c,v),coulumns);
}
}
}
}
vector <int> ans;
if(slover.solve(ans))puts("Yes");
else puts("No");
}
return 0;
}
Problem H: MMs
题意:M个结点的树,每个结点有一定数量的MMs,边有权值,询问使每个点一个MMs的最小花费,使用vector存邻接边,然后直接dfs即可
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <algorithm>
#include <queue>
#include <set>
#include <bitset>
using namespace std;
int n,m,u,v,w,c[100005];
int dep[100005];
long long ans;
vector <int> G[100005],W[100005];
bool vis[100005];
void dfs(int u)
{
dep[u]=c[u]-1;vis[u]=true;
int len=G[u].size(),w,v;
for(int i=0;i<len;++i)
{
v=G[u][i];w=W[u][i];
if(vis[v])continue;
dfs(v);
ans+=abs(dep[v])*(long long)w;
dep[u]+=dep[v];
}
}
int main()
{
while(scanf("%d",&n)==1)
{
for(int i=0;i<=n;++i){G[i].clear();W[i].clear();}
memset(vis,false,sizeof(vis));
for(int i=0;i<n-1;++i)
{
scanf("%d%d%d",&u,&v,&w);
G[u].push_back(v);
G[v].push_back(u);
W[u].push_back(w);
W[v].push_back(w);
}
for(int i=1;i<=n;++i)scanf("%d",c+i);
ans=0LL;dfs(1);
printf("%lld\n",ans);
}
return 0;
}
Problem J: Hapsunday
签到题
#include <cstring>
#include <iostream>
#include <cstdlib>
#include <cctype>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <queue>
using namespace std;
double a[66];
int main()
{
for(int i=1;i<=64;++i){
double sum=i;
for(int j=1;j<=i+1;++j){
sum/=j;
}
a[i]=sum;
}
int n;
while(scanf("%d",&n)==1){
double ans=0;
for(int i=1;i<=n;++i){
ans+=a[i];
}
printf("%.2lf\n",ans);
}
return 0;
}