版权声明:小蒟蒻的博客转载也请注明出处哦 https://blog.csdn.net/qq_42835823/article/details/82529602
WOJ3931
嘻嘻,这道题其实不算图论。(难以置信~~~)
抛开边不管,将每个点的值拍一下序。
第K天到的城市就将人减K。
所以从大到小得吃就好了,吃到的人小于0就break.
经过的城市不能再吃了,可以不管,因为前面能吃的调一下序就好了。
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
void read(int &x){
x=0;char s=getchar();
while(s>'9'||s<'0')s=getchar();
while(s<='9'&&s>='0'){x=(x<<3)+(x<<1)+s-'0';s=getchar();}
}
int n,m,a[200010];
long long s[200010],ans=0;
int main(){
read(n);read(m);
for(int i=1;i<=n;i++)read(a[i]);
int e,f;
for(int i=1;i<=m;i++)read(e),read(f);
sort(a+1,a+n+1);
for(int i=1;i<=n;i++){
e=a[n+1-i]-i+1;
if(e<=0)break;
ans+=e;
}
printf("%lld",ans);
return 0;
}
WOJ3932
解法见上,代码有点难。
#include<bits/stdc++.h>
using namespace std;
const int N=100005;
int mk[N],pri[N],cnt=0;
void prime(){//ai
for(int i=2;i<N;i++){
if(!mk[i])pri[++cnt]=i;
for(int j=1;j<=cnt&&1ll*i*pri[j]<N;j++){
mk[i*pri[j]]=pri[j];//最大质因子
if(i%pri[j]==0)break;
}
}
}
int k,a[505];
long long n;
pair<int,int>b[N];
int ok[N],v[N],num=0,tmp=0,m=0,bit=0;
void divide(int x){
tmp=0;
for(int i=1;1ll*pri[i]*pri[i]<=x&&i<=cnt;i++)
if(x%pri[i]==0){
b[++tmp]=make_pair(0,0);//不用一个一个地加
b[tmp].first=pri[i];
while(x%pri[i]==0)
b[tmp].second++,x/=pri[i];
if(!ok[pri[i]])
ok[pri[i]]=1,v[++num]=pri[i];
}
if(x>1)b[++tmp]=make_pair(x,1),v[++num]=x;return;//
}
long long mul;
bool check(int x){
if(n%x)return 0;//排除次方大于的数
divide(x);
for(int i=1;i<=tmp;i++){
mul=1;
for(int j=1;j<=b[i].second;j++)
mul=mul*b[i].first;
if((n/mul)%b[i].first==0)//排除次方小于的数
return 0;
}
return 1;
}
void check_zero(){
long long tt=n;
for(int i=0;i<bit;i++)
while(tt%v[i]==0)tt/=v[i];
if(tt>1){
puts("0");
exit(0);//退出程序
}
}
int cal(int x){
int ret=0;
for(int i=0;i<bit;i++)
if(x%v[i]==0)ret|=1<<i;
return ret;
}
long long f[1<<20];
int main(){
int pow=1;
prime();//素数线性筛
scanf("%lld%d",&n,&k);
for(int x,i=1;i<=k;i++){
scanf("%d",&x);
if(x==1){//特判
pow=2;continue;
}
if(check(x))a[++m]=x;
}
sort(v+1,v+num+1);
for(int i=1;i<=num;i++)//去重
if(v[i]!=v[i+1])v[bit++]=v[i];
check_zero();//判断n是否有可能
for(int i=1;i<=m;i++)
a[i]=cal(a[i]);//转二进制
//状压DP
f[0]=1;
for(int i=0;i<(1<<bit);i++)//要多一位
for(int j=1;j<=m;j++)
if((i&a[j])==0&&i<a[j])//不重复 严格按照小的乘大的(避免多算)
f[i|a[j]]+=f[i];
printf("%lld",f[(1<<bit)-1]*pow);
return 0;
}
WOJ3933
题解未完待续……