关于MOD&链式前向星-2015年9月25日

好久没写了,其实一直也在做,但是没心情写总结文章,所以还是以后做一点就写一点吧。

最近状态很差很差,打水题都过不了,我也是醉了。

重做了去年的两道noip题,D1T2和D2T3,里面包括了MOD运算。

MOD运算基本满足四则运算,所以很多表达式在模p意义下都是等价的,但除法除外。

但是还要注意,需要在非负情况下进行计算,当出现减法时,一定要加到正值再做。

另外注意溢出的问题,及时取模也是很重要的。

noip2014D1T2可以用链式前向星存图。

大概就是这样:

struct Edge{

  int to,next,w;

};

head[];

循环的时候就是这样:

for(int i=head[u];i!=-1;i=e[i].next)

也就是说head初始化为-1

还有addEdge:

void addEdge(int u,int v,int w){

  e[etot].to=v;

  e[etot].next=head[u];

  head[u]=etot++;

}

看起来还是挺方便的,对于稀疏图效果很好,也避免了使用静态链表,感觉静态链表也有点麻烦。

noip2014联合权值:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <string>
 5 #include <algorithm>
 6 using namespace std;
 7 const int maxn = 200000*2+10;
 8 const int MOD=10007; 
 9 struct Edge{
10     int to,next;
11 };
12 Edge e[maxn];
13 int etot=0;
14 int head[maxn];
15 int w[maxn];
16 int tot=0,max_w=0;
17 int n;
18 void addEdge(int u,int v){
19     e[etot].to=v;
20     e[etot].next=head[u];
21     head[u]=etot++;
22 }
23 void read_in(){
24     memset(head,-1,sizeof(head));
25     scanf("%d",&n);
26     for(int i=1;i<n;i++){
27         int u,v;
28         scanf("%d%d",&u,&v);
29         addEdge(u,v);
30         addEdge(v,u);
31     }
32     for(int i=1;i<=n;i++)scanf("%d",w+i);
33 }
34 void cal(int &x,int &y,int w){
35     if(w>=x){y=x; x=w;return;}
36     if(w>y){y=w;return;}
37 }
38 void solve(){
39     for(int i=1;i<=n;i++){
40         int sum=0;
41         int max_1=0,max_2=0;
42         for(int j=head[i];j!=-1;j=e[j].next){
43             cal(max_1,max_2,w[e[j].to]);
44             sum=(sum+w[e[j].to])%MOD;
45         }
46         if(max_1*max_2>max_w)max_w=max_1*max_2;
47         for(int j=head[i];j!=-1;j=e[j].next){
48             tot=(tot+((sum-w[e[j].to]+MOD)%MOD)*w[e[j].to])%MOD;
49         }
50     }
51     cout<<max_w<<' '<<tot%MOD<<endl;
52 }
53 int main(){
54     read_in();
55     solve();
56     return 0;
57 }

noip2014解方程

这道题比较高级,不过同样也是利用了众多表达式在模p意义下等价这一性质,所以只需要取几个素数p,把1到p代入方程求解,最后枚举方程的解,映射回1到p判断等不等于0就好了。复杂度max(p*n*pnum,m*pnum),所以p不能太大,差不多10000左右就可以了。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <string>
 5 #include <algorithm>
 6 using namespace std;
 7 const int maxn = 100+10;
 8 const int modNum=5;
 9 const int maxMod=21893+10;
10 const long long MOD[modNum]={10007,11261,14843,19997,21893};
11 long long a[maxn][modNum];
12 long long res[maxMod][modNum];
13 int ans[maxn];
14 int n,m;
15 void change(long long &x,string s,long long mod){
16     int len=s.size();
17     x=0;
18     if(s[0]=='-'){
19         for(int i=1;i<len;i++)x=(x*10+s[i]-'0')%mod;
20         x=-x;
21     }
22     else{
23         for(int i=0;i<len;i++)x=(x*10+s[i]-'0')%mod;
24     }
25 }
26 bool Jud(int x){
27     for(int i=0;i<modNum;i++)if(res[x%MOD[i]][i]!=0)return false;
28     return true;
29 }
30 int main(){
31     cin>>n>>m;
32     for(int i=0;i<=n;i++){
33         string x;
34         cin>>x;
35         for(int j=0;j<modNum;j++)change(a[i][j],x,MOD[j]);    
36     }
37     int tot=0;
38     for(int Mod=0;Mod<modNum;Mod++){
39         for(int p=1;p<MOD[Mod];p++){
40             //
41             long long current=0;
42             long long base=1;
43             // cal
44             for(int i=0;i<=n;i++){
45                 current=(current+base*a[i][Mod])%MOD[Mod];
46                 base=base*p%MOD[Mod];
47             }
48             // cal/
49             res[p][Mod]=current;
50             //
51         }
52     }
53     for(int i=1;i<=m;i++)if(Jud(i))ans[tot++]=i;
54     cout<<tot<<endl;
55     for(int i=0;i<tot;i++)cout<<ans[i]<<endl;
56     return 0;
57 }

 

posted @ 2015-09-25 09:51  JimmyLin^_^  阅读(158)  评论(0编辑  收藏  举报