//这里只写我已经A的。。
一、 1 0 9 + 7 10^9+7 109+7
You are given three non-negative integers, x, y, z. Your task is to find the smallest non-negative integer n with all of the following conditions:
- n mod 17=x
- n mod 107=y
- n mod 1000000007(=109+7)=z
Solution
- 第一眼:中国剩余定理。
- 后来发现不用
- 由于1000000007特别大
- 所以符合范围的数肯定不会很多
- 不断暴力枚举即可
- 经过
严格的证明可以得出最多也就17*107次 - 所以可以AC
Code
#include<bits/stdc++.h>
using namespace std;
#define int long long
int x,y,z;
int ans=0;
signed main(){
scanf("%lld %lld %lld",&x,&y,&z);
ans=z;
for (;ans%17!=x || ans%107!=y;ans+=1000000007);
printf("%lld",ans);
return 0;
}
二、Coins
There are 1-, 5-, 10-, 50-, 100-, 500- yen coins, and you have an infinite number of coins of each type.
For a given positive integer x, let f(x) be the smallest number of coins you have to use to pay exactly x yen. For example, f(2018)=9 because 2018=1+1+1+5+10+500+500+500+500.
You are given a positive integer N. Count the number of positive integers x such that f(x)=N.
Solution
- 第一眼是完全背包
- 一看范围发现不行
- 仔细看了一眼题面,发现要是最小的??
- 这意味着只能用4个1,1个5,4个10,1个50,4个100!!
- 所以我们就可以根据这个暴力了
- 500填几个都行
- 时间复杂度非常可观
Code
#include<bits/stdc++.h>
using namespace std;
long long n;
int ans=0;
int main(){
scanf("%lld",&n);
n-=n/500;
for (int yi=0;yi<5;yi++)
for (int wu=0;wu<2;wu++)
for (int shi=0;shi<5;shi++)
for (int ws=0;ws<2;ws++)
for (int yb=0;yb<5;yb++)
if (yi+wu+shi+ws+yb <= n) ans++;
printf("%d",ans);
return 0;
}
三、Yet another vector problem
You’re given a 0-based array a of length n. Answer Q queries of form: what is sum of elements a[i], such as i modulo p = q, for given p and q.
Solution
- 第一想法:dp,一看范围,不对啊??
- 不管,先把dp敲了一遍,交了一发没过,想优化。
- 不过。。这题似乎可以卡范围??
- 仔细算了一下范围,发现当n>=100时,这是可以卡过的??
- 于是就是暴力与正解的结合,交了一发,A了
Code
#include <bits/stdc++.h>
using namespace std;
#define gc getchar()
int n,q;
int a[100010];
int f[100010][110];
int read(){
char ch=gc;
int ans=0;
bool f=0;
while (ch<'0' || ch>'9') f=ch=='-',ch=gc;
while (ch>='0' && ch<='9') ans=(ans<<1)+(ans<<3)+ch-48,ch=gc;
return f?-ans:ans;
}
void work(int x,int y){
long long ans=0;
for (signed int i=x;i<n;i+=y) ans+=a[i]*1ll;
printf("%lld\n",ans);
return;
}
int main(void)
{
n=read(),q=read();
for (int i=0;i<n;i++) a[i]=read();
for (signed int i=n-1;i>=0;i--)
for (signed int j=0;j<=105;j++)
if (i+j>n-1) f[i][j]=a[i];
else f[i][j] = f[i+j][j]+a[i];
for (signed int i=1;i<=q;i++){
int P,Q;
P=read(),Q=read();
if (Q == 0) {printf("0\n");continue;}
if (Q<=95) printf("%d\n",f[P][Q]);
else work(P,Q);
}
return 0;
}
四、Grouping
Suppose there are N people in ZJU, whose ages are unknown. We have some messages about them. The i-th message shows that the age of person si is not smaller than the age of person ti. Now we need to divide all these N people into several groups. One’s age shouldn’t be compared with each other in the same group, directly or indirectly. And everyone should be assigned to one and only one group. The task is to calculate the minimum number of groups that meet the requirement.
Solution
- 对于同一个环中的人,肯定不能互相在一起
- 考虑强连通分量缩点,点权为这个连同分量中点的个数
- 同样,在同一条链中的人肯定也不能互相分到一组
- 所以问题转化为缩点后求新图的最长链
- 不过,这个代码是有锅的
Code
#include<bits/stdc++.h>
using namespace std;
int n,m;
struct node{
int x,y,Next;
}e[600100];
int X[100010],Y[100010];
int fam[100010];
int Dp[101100];
int in[1010000];
int sta[100010];
vector < int > a[200010];
vector <int> scc[200010];
int linkk[100010];
int dfn[100010];
int low[100100];
int num,top=0,len=0,cnt=0;
bool isi[100100];
int con[1000010];
void insert(int x,int y){
e[++len] = (node){x,y,linkk[x]};
linkk[x] = len;
}
void tarjan(int x){
dfn[x] = low[x] = ++num;
sta[++top] = x;
isi[x] = 1;
for (int i=linkk[x];i;i=e[i].Next){
int y=e[i].y;
if (!dfn[y]) tarjan(y) , low[x] = min(low[x] , low[y]);
else if (isi[y]) low[x] = min(low[x] , dfn[y]);
}
if (dfn[x] == low[x]) {
cnt ++ ;
int y;
do {
y = sta[top--];
isi[y] = 0;
fam[y] = cnt;
con[cnt] ++;
scc[cnt].push_back(y);
}while( x != y );
}
}
int dp(int x){
if (Dp[x] > 0) return Dp[x];
Dp[x] = 0;
// cout<<"OK:"<<x<<endl;
for (int i=0;i<a[x].size();i++){
int y=a[x][i];
Dp[x] = max(Dp[x] , dp(y));
}
Dp[x] += scc[x].size();
// cout<<"x:"<<x<<' '<<Dp[x]<<' '<<con[x]<<endl;
return Dp[x];
}
void work(){
int ans=0;
len=0 , top=0 ,cnt=0 , num=0;
memset(linkk,0,sizeof linkk);
memset(fam,0,sizeof fam);
memset(in,0,sizeof in);
memset(sta,0,sizeof sta);
memset(Dp,0,sizeof(Dp));
memset(dfn,0,sizeof dfn);
memset(low,0,sizeof low);
memset(con,0,sizeof(con));
memset(isi,0,sizeof(isi));
for (int i=1;i<100009;i++) a[i].clear();
for (int i=1;i<100009;i++) scc[i].clear();
for (int i=1,x,y;i<=m;i++)
scanf("%d %d",&X[i],&Y[i]),insert(X[i],Y[i]);
for (int i=1;i<=n;i++)
if (!dfn[i]) tarjan(i);
len=0;
memset(linkk,0,sizeof(linkk));
for (int i=1;i<=m;i++)
if (fam[X[i]] != fam[Y[i]]) a[fam[X[i]]].push_back(fam[Y[i]]),in[fam[Y[i]]]++;
// cout<<cnt<<endl;
// for (int i=1;i<=n;i++) cout<<fam[i]<<' ';
// cout<<endl;
// for (int i=1;i<=cnt;i++) cout<<in[i]<<' ';
// cout<<"i:"<<i<<' ';
// for (int j=linkk[i];j;j=e[j].Next) cout<<e[j].y<<' ';
// cout<<endl<<"------------------------------"<<endl;
// }
for (int i=1;i<=cnt;i++)
if (!in[i]) ans = max(ans,dp(i));
printf("%d\n",ans);
}
int main(){
while (~scanf("%d %d",&n,&m)) work();
}