P3811 【模板】乘法逆元
对于一个数求逆元 这个简单 就是根据费马小定理 快速幂,ksm(i,mod-2,mod); 但是题目要求是求1~n所有的逆元 所以这样超时 所以 必须想一个复杂度低的,对于一个mod来说 可以设为 p=ki+r k是商 r是余数,那么可以进行转换 ,ki+r=0(mod p); 然后两方乘r-1 , i-1 得到i-1=-kr-1 ,i-1=-[P/i](pmod i )-1,所以就能找到逆元了
#include <bits/stdc++.h>
#include <iostream>
#define int long long
using namespace std;
const int N=3e6+10,M=5e5+10;
typedef pair<int,int> PII;
const int mod=80112002;
int f[N];
int n,m,p;
signed main(){
ios::sync_with_stdio(0);
cout.tie(0);
cin>>n>>p;
f[1]=1;
for(int i=2;i<=n;i++){
f[i]=(p-p/i)*(f[p%i])%p;
}
for(int i=1;i<=n;i++){
cout<<f[i]<<'\n';
}
}
P4568 [JLOI2011] 飞行路线
分层图的概念 对于一条路线来说 我可以往下走走到下一个图去 然后这条线是不用钱的 就可以通到k个图去 然后对于我们来说就是跑到第k层图的终点需要花的多少钱 然后 对于任何一个图的终点都要连通 这样就不会出错
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef pair<int, int> PII;
const int N = 111111,M=2500001;
int n, m,k;
int s,t;
bool st[N];
int h[N],ne[M],e[M],dist[N],w[M],idx;
void add(int a,int b,int c=0){
e[idx]=b;w[idx]=c;
ne[idx]=h[a];
h[a]=idx++;
}
void dijks(){
memset(dist,0x3f,sizeof dist);
dist[s]=0;
priority_queue<PII,vector<PII>,greater<PII>> q;
q.push({0,s});
while(q.size()){
auto t=q.top();q.pop();
int ver=t.second,d=t.first;
if(st[ver])continue;
st[ver]=true;
for(int i=h[ver];~i;i=ne[i]){
int j=e[i];
if(dist[j]>dist[ver]+w[i]){
dist[j]=dist[ver]+w[i];
q.push({dist[j],j});
}
}
}
}
signed main() {
memset(h,-1,sizeof h);
cin >> n >>m>>k;
cin>>s>>t;
while(m--){
int a,b,c;cin>>a>>b>>c;
add(a,b,c);
add(b,a,c);
for(int i=1;i<=k;i++){
add(a+(i-1)*n,b+i*n);
add(b+(i-1)*n,a+i*n);
add(a+i*n,b+i*n,c);
add(b+i*n,a+i*n,c);
}
}
for(int i=1;i<=k;i++){
add(t+(i-1)*n,t+i*n);
}
dijks();
cout<<dist[t+k*n]<<endl;
}
P1106 删数问题
首先会出现前导0的情况 所以不能常规处理 两个方案 一是找到k个前面最小的数 的位置 然后把前面全删了 ,有因为遇到0 那么前面的一定会删掉 0也不会输出 ;
还有另一种方案 就是每次找的时候 找到0 那么就是前面的全删 不存在表里 然后 遇到0就这样 直到 达到删除了那么多个数 过着 这里面的数已经够k个 ,就不用删
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=520;
int n,m,T;
typedef pair<int,int> PII;
int a[N];
signed main(){
string s;cin>>s;cin>>m;
n=s.size();
for(int i=1;i<=n;i++){
a[i]=s[i-1]-'0';
}
int t=n-m;
int cnt=0;
int j=1;
bool flag=false;
while(cnt<t){
int tt=j;
for(int k=j;k<=m+j;k++)if(a[tt]>a[k])tt=k;
if(a[tt])flag=true;
if(flag)cout<<a[tt];
m-=tt-j;
j=tt+1;
cnt++;
}
if(!flag)cout<<0;
}
最大食物链
dfs 和拓扑排序 都是可以的,需要存一下入度 出度
#include <bits/stdc++.h>
#include <iostream>
#define int long long
using namespace std;
const int N=5010,M=5e5+10;
typedef pair<int,int> PII;
const int mod=80112002;
int h[N],e[M],ne[M];
int f[N];
bool st[N];
int in[N];
int ou[N];
int idx;
int n,m;
void add(int a,int b){
ne[idx]=h[a];
e[idx]=b;
h[a]=idx++;
}
void solve(){
queue<int> q;
for(int i=1;i<=n;i++){
if(in[i]==0){
q.push(i);
f[i]=1;
}
}
int ans=0;
while(q.size()){
int t=q.front();q.pop();
for(int i=h[t];i!=-1;i=ne[i]){
int j=e[i];
--in[j];
f[j]=(f[j]+f[t])%mod;
if(in[j]==0)q.push(j);
}
}
for(int i=1;i<=n;i++){
if(!ou[i]){
ans=(ans+f[i])%mod;
}
}
cout<<ans<<endl;
}
signed main(){
cin>>n>>m;
memset(h,-1,sizeof h);
while(m--){
int a,b;cin>>a>>b;
add(a,b);
in[b]++;
ou[a]++;
}
solve();
}
#include <bits/stdc++.h>
#include <iostream>
#define int long long
using namespace std;
const int N=5010,M=5e5+10;
typedef pair<int,int> PII;
const int mod=80112002;
int h[N],e[M],ne[M];
int f[N];
bool st[N];
int in[N];
int ou[N];
int idx;
int n,m;
void add(int a,int b){
ne[idx]=h[a];
e[idx]=b;
h[a]=idx++;
}
int dfs(int t){
if(ou[t]==0)return 1;
if(f[t])return f[t];
int ans=0;
for(int i=h[t];i!=-1;i=ne[i]){
int j=e[i];
ans+=dfs(j)%mod;
}
return f[t]=ans%mod;
}
void solve(){
queue<int> q;
for(int i=1;i<=n;i++){
if(in[i]==0){
q.push(i);
}
}
int ans=0;
while(q.size()){
int t=q.front();q.pop();
for(int i=h[t];i!=-1;i=ne[i]){
int j=e[i];
ans=(ans+dfs(j)%mod)%mod;
}
}
cout<<ans<<endl;
}
signed main(){
cin>>n>>m;
memset(h,-1,sizeof h);
while(m--){
int a,b;cin>>a>>b;
add(a,b);
in[b]++;
ou[a]++;
}
solve();
}